使用gin路由器为net.Conn提供服务的Golang代码。

huangapple go评论81阅读模式
英文:

golang: serving net.Conn using a gin router

问题

我有一个处理传入TCP连接的函数:

func Handle(conn net.Conn) error {
	// ...
}

此外,我有一个已初始化的gin路由器,并实现了处理函数:

router := gin.New()
router.GET(...)
router.POST(...)

router.Run(addr) 调用将在 addr 上启动一个独立的HTTP服务器。

有没有办法在不运行独立的HTTP服务器的情况下,使用这个路由器在 Handle 函数中处理传入的连接?

英文:

I have a function that handles an incoming TCP connection:

func Handle(conn net.Conn) error {
	// ...
}

Also, I have an initialized gin router with implemented handles:

router := gin.New()
router.GET(...)
router.POST(...)

The router.Run(addr) call will start a separate HTTP server on the addr.

Is there any way to handle incoming connections inside the Handle function using this router without running a separate HTTP server?

答案1

得分: 4

创建一个接受连接的 net.Listener 实现,通过在通道上接收连接:

type listener struct {
    ch   chan net.Conn
    addr net.Addr
}

// newListener 创建一个通道监听器。addr 参数是监听器的网络地址。
func newListener(addr net.Addr) *listener {
    return &listener{
        ch:   make(chan net.Conn),
        addr: addr,
    }
}

func (l *listener) Accept() (net.Conn, error) {
    c, ok := <-l.ch
    if !ok {
        return nil, errors.New("closed")
    }
    return c, nil
}

func (l *listener) Close() error { return nil }

func (l *listener) Addr() net.Addr { return l.addr }

通过将连接发送到通道来处理连接:

func (l *listener) Handle(c net.Conn) error {
    l.ch <- c
    return nil
}

下面是如何将它们整合在一起的方法:

  • 创建监听器:
s := newListener(someAddr)
  • 像往常一样配置 Gin 引擎。
router := gin.New()
router.GET(...)
router.POST(...)
  • 使用通道监听器和 Gin 引擎在一个 goroutine 中运行 net/http 服务器:
err := http.Serve(s, router)
if err != nil {
    // 处理错误
}
  • 在调度代码中,调用 s.Handle(c) 将连接传递给 net/http 服务器,然后传递给 Gin 引擎。
英文:

Create a net.Listener implementation that accepts connections by receiving on a channel:

type listener struct {
	ch   chan net.Conn
	addr net.Addr
}

// newListener creates a channel listener. The addr argument
// is the listener&#39;s network address.
func newListener(addr net.Addr) *listener {
	return &amp;listener{
		ch:   make(chan net.Conn),
		addr: addr,
	}
}

func (l *listener) Accept() (net.Conn, error) {
	c, ok := &lt;-l.ch
	if !ok {
		return nil, errors.New(&quot;closed&quot;)
	}
	return c, nil
}

func (l *listener) Close() error { return nil }

func (l *listener) Addr() net.Addr { return l.addr }

Handle connections by sending to the channel:

func (l *listener) Handle(c net.Conn) error {
	l.ch &lt;- c
	return nil
}

Here's how to tie it all together:

  • Create the listener:

      s := newListener(someAddr)
    
  • Configure the Gin engine as usual.

      router := gin.New()
      router.GET(...)
      router.POST(...)
    
  • Run the net/http server in a goroutine using the channel listener and the Gin engine:

      err := http.Serve(s, router)
      if err != nil {
          // handle error
      }
    
  • In your dispatching code, call the s.Handle(c) to pass the connection to the net/http server and then on to the Gin engine.

答案2

得分: 0

对于那些需要使用单个路由器处理来自多个端口的TCP连接的人,我最终找到了一个解决方法。不是在一个端口上运行HTTP服务器,而是使用UNIX套接字运行它,使用router.RunUnix(socketName)。完整的解决方案包括三个步骤:

  1. 运行一个HTTP服务器,通过UNIX套接字监听,使用router.RunUnix(socketName)

  2. Handle函数内,读取连接中传入的字节,并将它们发送到套接字。之后,从套接字读取HTTP响应,并将其写入连接。

  3. 关闭连接。

英文:

For those who have a similar task - handle TCP connections from multiple ports using a single router, here's a workaround that I eventually found. Instead of running an HTTP server on a port, I run it with a UNIX socket using router.RunUnix(socketName). The full solution consists of three steps:

  1. Run a HTTP server to listen through a UNIX socket using router.RunUnix(socketName)

  2. Inside the Handle function read the incoming bytes from the connection and send them to the socket. After that, read the HTTP response from the socket and write it into the connection.

  3. Close the connection.

huangapple
  • 本文由 发表于 2022年2月17日 04:23:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/71148822.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定