Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimanakah Saya Boleh Mengakses Soket Dasar Respons HTTP dalam Go?

Bagaimanakah Saya Boleh Mengakses Soket Dasar Respons HTTP dalam Go?

Linda Hamilton
Linda Hamiltonasal
2024-11-04 22:39:02591semak imbas

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

Mengakses Soket Dasar Respons HTTP

Dalam Go, anda mungkin menghadapi situasi di mana anda perlu mengakses soket asas HTTP tindak balas. Biasanya, mengakses soket diperlukan apabila anda ingin melakukan operasi khusus platform padanya, seperti TCP_INFO. Walaupun tiada cara mudah untuk mendapatkan soket terus daripada respons HTTP, terdapat beberapa pendekatan yang boleh anda terokai:

1. Menggunakan Kunci Konteks (Go 1.13 ):
Setelah Go 1.13 dikeluarkan, ia dijangka menyokong penyimpanan net.Conn dalam Konteks Permintaan. Ini menyediakan kaedah yang bersih dan mudah:

<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. Pemetaan Sambungan melalui Alamat Jauh (TCP):
Untuk pelayan mendengar pada TCP, setiap sambungan mempunyai nilai net.Conn.RemoteAddr().String() yang unik. Nilai ini boleh digunakan sebagai kunci kepada peta global sambungan:

<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. Mengatasi Alamat Jauh untuk Soket UNIX:
Untuk soket UNIX, net.Conn.RemoteAddr().String() sentiasa mengembalikan "@", menjadikannya tidak sesuai untuk pemetaan. Untuk mengatasinya:

  • Override net.Listener.Accept()
  • Gunakan override itu untuk menetapkan rentetan unik kepada setiap sambungan melalui 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>

Atas ialah kandungan terperinci Bagaimanakah Saya Boleh Mengakses Soket Dasar Respons 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