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

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

DDD
DDDoriginal
2024-11-07 10:36:03279parcourir

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

Récupération du socket sous-jacent d'une réponse net/http

Dans le domaine de la programmation réseau avec le package net/http de Go, nous pouvons parfois avoir besoin d'accéder directement au sous-jacent connexion réseau (net.Conn).

Énoncé du problème

Un développeur essaie de servir des fichiers en utilisant net/http, mais rencontre un problème : avoir besoin d'accéder au socket sous-jacent de http.ResponseWriter dans la fonction de gestionnaire ( net.Conn) pour effectuer des appels système spécifiques à la plate-forme.

Solution de contournement

Dans Go 1.13 et supérieur, net.Conn peut être stocké dans le contexte de la requête en suivant ces étapes :

  • Utilisez la fonction SaveConnInContext pour enregistrer net. .Conn est enregistré dans le contexte de la demande.
  • Récupérez net.Conn de la requête à l'aide de la fonction GetConn.

Avant cette version, il existait deux alternatives :

Utiliser la chaîne d'adresse distante

Pour écouter sur un port TCP Pour les serveurs , net.Conn.RemoteAddr().String() est unique pour chaque connexion et peut être utilisée comme clé de la carte de connexion globale.

Remplacer net.Listener.Accept()

Pour les serveurs écoutant sur des sockets UNIX, nous pouvons remplacer net.Listener.Accept() pour utiliser le descripteur de fichier pour renvoyer une valeur plus unique.

Exemple de code

Go 1.13 et supérieur

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

Pour la connexion 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>

Pour les connexions 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>

Grâce à ces méthodes, les développeurs peuvent facilement accéder au socket sous-jacent de http.ResponseWriter, leur ouvrant ainsi une gamme de possibilités de gestion réseau personnalisée.

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