In the realm of network programming with Go's net/http package,有時我們可能需要直接存取底層的網路連線(net.Conn)。
一位開發者正在嘗試使用net/http為文件提供服務,卻遇到了一個問題:需要訪問處理程序函數中http.ResponseWriter的底層套接字( net.Conn),以便進行特定於平台的系統呼叫。
在Go 1.13及更高版本中,net.Conn可以透過以下步驟儲存在請求上下文中:
在此版本之前,有兩種替代方法:
使用遠端位址字串
對於在TCP連接埠上偵聽的伺服器,net.Conn.RemoteAddr().String()對於每個連線都是唯一的,可以用作全域連線映射的鍵。
覆蓋net.Listener.Accept ()
對於在UNIX套接字上偵聽的伺服器,我們可以重寫net.Listener.Accept()以使用文件描述符來傳回一個更獨特的值。
Go 1.13及更高版本
<code class="go">// SaveConnInContext stores the net.Conn in the request context. func SaveConnInContext(ctx context.Context, c net.Conn) context.Context { return context.WithValue(ctx, ConnContextKey, c) } // GetConn retrieves the net.Conn from the request context. func GetConn(r *http.Request) net.Conn { return r.Context().Value(ConnContextKey).(net.Conn) }</code>
對於TCP.連接
<code class="go">// ConnStateEvent handles connection state events. 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()) } } // GetConn retrieves the net.Conn from a map using the remote address as a key. func GetConn(r *http.Request) net.Conn { return conns[r.RemoteAddr] }</code>
對於TCP連接
<code class="go">// NewUnixListener creates a new UNIX listener with a modified Accept() method. func NewUnixListener(path string) (net.Listener, error) { // ... (setup code) l, err := net.Listen("unix", path) if err != nil { return nil, err } return NewConnSaveListener(l), nil } // NewConnSaveListener wraps a listener and overrides the Accept() method. func NewConnSaveListener(wrap net.Listener) net.Listener { return connSaveListener{wrap} } // remoteAddrPtrConn overrides the RemoteAddr() method to return a unique value. type remoteAddrPtrConn struct { net.Conn ptrStr string } func (self remoteAddrPtrConn) RemoteAddr() net.Addr { return remoteAddrPtr{self.ptrStr} } // remoteAddrPtr implements the net.Addr interface. type remoteAddrPtr struct { ptrStr string } func (remoteAddrPtr) Network() string { return "" } func (self remoteAddrPtr) String() string { return self.ptrStr } // Accept overrides the default Accept() method to store the net.Conn in a map. 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 }</code>對於TCP. 對於UNIX連接透過這些方法,開發人員可以輕鬆存取http.ResponseWriter的底層套接字,從而為其自訂網路處理開啟了一系列可能性。
以上是如何在 Go 中存取 net/http 回應的底層套接字?的詳細內容。更多資訊請關注PHP中文網其他相關文章!