Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimanakah Saya Boleh Mengakses Soket Pendasar bagi Respons net/http dalam Go?

Bagaimanakah Saya Boleh Mengakses Soket Pendasar bagi Respons net/http dalam Go?

DDD
DDDasal
2024-11-07 10:36:03371semak imbas

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

Mendapatkan semula Soket Pendasar bagi net/http Response

Dalam bidang pengaturcaraan rangkaian dengan pakej net/http Go, kadangkala kita mungkin perlu mengakses terus yang mendasari sambungan rangkaian(net.Conn).

Pernyataan Masalah

Pemaju cuba menyediakan fail menggunakan net/http, tetapi menghadapi masalah: memerlukan akses kepada soket asas http.ResponseWriter dalam fungsi pengendali ( net.Conn) untuk membuat panggilan sistem khusus platform.

Penyelesaian

Dalam Go 1.13 dan ke atas, net.Conn boleh disimpan dalam konteks permintaan dengan mengikut langkah berikut:

  • Gunakan fungsi SaveConnInContext untuk menyimpan bersih .Conn disimpan ke konteks permintaan.
  • Dapatkan semula net.Conn daripada permintaan menggunakan fungsi GetConn.

Sebelum keluaran ini, terdapat dua alternatif:

Gunakan rentetan alamat jauh

Untuk mendengar pada port TCP Untuk pelayan , net.Conn.RemoteAddr().String() adalah unik untuk setiap sambungan dan boleh digunakan sebagai kunci kepada peta sambungan global.

Override net.Listener.Accept()

Untuk pelayan mendengar pada soket UNIX, kami boleh mengatasi net.Listener.Accept() untuk Gunakan deskriptor fail untuk kembali nilai yang lebih unik.

Contoh Kod

Pergi 1.13 dan ke atas

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

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

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

Melalui kaedah ini, pembangun boleh mengakses soket asas http.ResponseWriter dengan mudah, membuka rangkaian pengendalian rangkaian tersuai untuk mereka.

Atas ialah kandungan terperinci Bagaimanakah Saya Boleh Mengakses Soket Pendasar bagi Respons net/http dalam Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn