首頁  >  文章  >  後端開發  >  如何在 Go 中存取 net/http 回應的底層套接字?

如何在 Go 中存取 net/http 回應的底層套接字?

DDD
DDD原創
2024-11-07 10:36:03279瀏覽

How Can I Access the Underlying Socket of a net/http Response in Go?

Retrieving the Underlying Socket of a net/http Response

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可以透過以下步驟儲存在請求上下文中:

  • 使用SaveConnInContext函數將net .Conn保存到請求上下文中。
  • 使用GetConn函數從請求中擷取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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn