ホームページ  >  記事  >  バックエンド開発  >  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?

net/http 応答の基になるソケットの取得

Go の net/http パッケージを使用したネットワーク プログラミングの領域では、基になるソケットに直接アクセスする必要がある場合があります。ネットワーク接続(net.Conn)。

問題ステートメント

開発者は net/http を使用してファイルを提供しようとしていますが、問題が発生しました: ハンドラー関数 (net.Conn) で http.ResponseWriter の基礎となるソケットにアクセスする必要があります。プラットフォーム固有のシステムコールを実行します。

回避策

Go 1.13 以降では、次の手順に従って net.Conn をリクエスト コンテキストに保存できます:

  • SaveConnInContext 関数を使用して net を保存します.Conn はリクエスト コンテキストに保存されます。
  • GetConn 関数を使用してリクエストから net.Conn を取得します。

このリリースより前には、次の 2 つの代替手段がありました。

リモート アドレス文字列を使用する

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>

UNIX 接続の場合

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

これらのメソッドを通じて、開発者は http.ResponseWriter の基礎となるソケットに簡単にアクセスでき、さまざまなカスタム ネットワーク処理の可能性が広がります。

以上がGo で net/http 応答の基になるソケットにアクセスするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。