在 Go 的 net/http 响应中获取底层 Socket
Go 的 net/http 包为构建 HTTP 服务器提供了一个方便的框架。但是,在某些情况下,您可能需要访问响应流的底层套接字。本文通过探索检索套接字连接的各种方法来解决这一需求。
Go 1.13 之前
Go 1.13 之前,获取底层套接字需要更复杂的技术。这里有两种方法:
基于事件的跟踪(仅限 TCP 连接):
对于通过 TCP 端口的连接,您可以利用 net.Listener。 ConnState 事件处理程序用于跟踪活动连接及其关联的套接字。此信息可以存储在全局映射中以供以后检索。
<code class="go">var conns = make(map[string]net.Conn) func ConnStateEvent(conn net.Conn, event http.ConnState) { if event == http.StateActive { conns[conn.RemoteAddr().String()] = conn } else if event == http.StateHijacked || event == http.StateClosed { delete(conns, conn.RemoteAddr().String()) } } func GetConn(r *http.Request) (net.Conn) { return conns[r.RemoteAddr] }</code>
监听器覆盖(Unix 套接字):
Unix 套接字需要更复杂的方法,因为它们缺乏每个连接的唯一标识符。一种解决方案是重写 net.Listener.Accept 方法,为每个连接分配唯一的字符串,并将这些字符串用作存储套接字信息的键。
<code class="go">func NewConnSaveListener(wrap net.Listener) (net.Listener) { return connSaveListener{wrap} } func (self connSaveListener) Accept() (net.Conn, error) { conn, err := self.Listener.Accept() ptrStr := fmt.Sprintf("%d", &conn) conns[ptrStr] = conn return remoteAddrPtrConn{conn, ptrStr}, err } func GetConn(r *http.Request) (net.Conn) { return conns[r.RemoteAddr] }</code>
Go 1.13 和超越
随着 Go 1.13 的发布,提供了更简单的解决方案:
基于上下文的存储:
从 Go 1.13 开始,net.Conn 可以存储在 HTTP 请求的上下文中。这提供了一种干净高效的方式来访问套接字连接。
<code class="go">type contextKey struct { key string } var ConnContextKey = &contextKey{"http-conn"} func SaveConnInContext(ctx context.Context, c net.Conn) (context.Context) { return context.WithValue(ctx, ConnContextKey, c) } func GetConn(r *http.Request) (net.Conn) { return r.Context().Value(ConnContextKey).(net.Conn) }</code>
通过了解这些技术,您可以有效地检索 net/http 响应处理程序中的底层套接字,从而启用自定义操作和特定于平台的功能。
以上是如何访问 Go 的 net/http 响应中的底层套接字?的详细内容。更多信息请关注PHP中文网其他相关文章!