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

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

Linda Hamilton
Linda Hamilton原創
2024-11-04 22:39:02591瀏覽

How Can I Access the Underlying Socket of an HTTP Response in Go?

存取HTTP 回應的底層套接字

在Go 中,你可能會遇到需要存取HTTP 底層套接字的情況回覆.通常,當您想要對其執行特定於平台的操作(例如 TCP_INFO)時,需要存取套接字。雖然沒有直接從HTTP 回應取得套接字的簡單方法,但您可以探索以下幾種方法:

1.使用Context Key (Go 1.13 ):
Go 1.13發布後,預計將支援在請求上下文中儲存net.Conn。這提供了一種乾淨且簡單的方法:

<code class="go">package main

import (
  "net/http"
  "context"
  "net"
  "log"
)

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)
}

func main() {
  http.HandleFunc("/", myHandler)
  server := http.Server{
    Addr: ":8080",
    ConnContext: SaveConnInContext,
  }
  server.ListenAndServe()
}

func myHandler(w http.ResponseWriter, r *http.Request) {
  conn := GetConn(r)
  ...
}</code>

2.透過遠端位址(TCP) 映射連接:
對於偵聽TCP 的伺服器,每個連接都有一個唯一的net.Conn.RemoteAddr().String() 值。該值可以用作全域連接映射的鍵:

<code class="go">package main

import (
  "net/http"
  "net"
  "fmt"
  "log"
)

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]
}

func main() {
  http.HandleFunc("/", myHandler)
  server := http.Server{
    Addr: ":8080",
    ConnState: ConnStateEvent,
  }
  server.ListenAndServe()
}

func myHandler(w http.ResponseWriter, r *http.Request) {
  conn := GetConn(r)
  ...
}</code>

3。覆蓋 UNIX 套接字的遠端位址:
對於 UNIX 套接字,net.Conn.RemoteAddr().String() 總是傳回“@”,使其不適合對應。要克服這個問題:

  • 重寫net.Listener.Accept()
  • 使用該重寫透過net.UnixConn.File() 為每個連線分配唯一的字串
<code class="go">package main

import (
  "net/http"
  "net"
  "os"
  "golang.org/x/sys/unix"
  "fmt"
  "log"
)

// ... (code omitted for brevity)

func main() {
  http.HandleFunc("/", myHandler)
  listenPath := "/var/run/go_server.sock"
  l, err := NewUnixListener(listenPath)
  if err != nil {
    log.Fatal(err)
  }
  defer os.Remove(listenPath)
  server := http.Server{
    ConnState: ConnStateEvent,
  }
  server.Serve(NewConnSaveListener(l))
}
// ... (code omitted for brevity)</code>

以上是如何在Go中存取HTTP回應的底層套接字?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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