Maison  >  Article  >  développement back-end  >  Comment puis-je accéder au socket sous-jacent d’une réponse HTTP dans Go ?

Comment puis-je accéder au socket sous-jacent d’une réponse HTTP dans Go ?

Linda Hamilton
Linda Hamiltonoriginal
2024-11-04 22:39:02591parcourir

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

Accès au socket sous-jacent d'une réponse HTTP

Dans Go, vous pouvez rencontrer des situations dans lesquelles vous devez accéder au socket sous-jacent d'une réponse HTTP réponse. En règle générale, l'accès au socket est requis lorsque vous souhaitez y effectuer des opérations spécifiques à la plate-forme, telles que TCP_INFO. Bien qu'il n'existe aucun moyen simple d'obtenir le socket directement à partir de la réponse HTTP, vous pouvez explorer plusieurs approches :

1. Utilisation de la clé de contexte (Go 1.13) :
Une fois Go 1.13 publié, il est prévu de prendre en charge le stockage de net.Conn dans le contexte de requête. Cela fournit une méthode propre et simple :

<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. Mappage de connexion par adresse distante (TCP) :
Pour les serveurs écoutant sur TCP, chaque connexion a une valeur net.Conn.RemoteAddr().String() unique. Cette valeur peut être utilisée comme clé d'une carte globale des connexions :

<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. Remplacement de l'adresse distante pour les sockets UNIX :
Pour les sockets UNIX, net.Conn.RemoteAddr().String() renvoie toujours "@", ce qui le rend impropre au mappage. Pour surmonter cela :

  • Remplacez net.Listener.Accept()
  • Utilisez ce remplacement pour attribuer une chaîne unique à chaque connexion via 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>

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn