Comment arrêter gracieusement un serveur d'écoute dans Go
Dans Go, la fonction Listen.Accept bloque l'exécution, ce qui rend difficile la résiliation d'un serveur d'écoute. serveur d'écoute avec élégance. Pour déterminer quand arrêter le serveur, une approche consiste à fermer le socket d’écoute et à détecter l’erreur spécifique indiquant une connexion réseau fermée. Cependant, cette erreur n'est pas exportée par le package net, ce qui oblige les développeurs à recourir à une gestion des erreurs délicate.
Heureusement, il existe une solution plus élégante. En utilisant un canal terminé, vous pouvez signaler au serveur de s'arrêter avant de fermer la connexion. Voici comment cela peut être implémenté avec un exemple de code :
package main import ( "io" "log" "net" "sync" "time" ) // Echo server struct type EchoServer struct { listen net.Listener done sync.WaitGroup } // Respond to incoming connection // // Write the address connected to then echo func (es *EchoServer) respond(remote *net.TCPConn) { defer remote.Close() _, err := io.Copy(remote, remote) if err != nil { log.Printf("Error: %s", err) } } // Listen for incoming connections func (es *EchoServer) serve() { for { conn, err := es.listen.Accept() if err != nil { select { case <-es.done: // Server has been stopped, so we can exit without showing the error. default: log.Printf("Accept failed: %v", err) } return } es.done.Add(1) // Increment the waitgroup for each incoming connection go func() { es.respond(conn.(*net.TCPConn)) es.done.Done() // Decrement the waitgroup when done handling the connection }() } } // Stop the server by closing the listening listen func (es *EchoServer) stop() { es.done.Wait() // Wait for all outstanding connections to finish handling es.listen.Close() // Now it the Accept will have an error above } // Make a new echo server func NewEchoServer(address string) *EchoServer { listen, err := net.Listen("tcp", address) if err != nil { log.Fatalf("Failed to open listening socket: %s", err) } es := &EchoServer{ listen: listen, } es.done.Add(1) go es.serve() return es } // Main func main() { log.Println("Starting echo server") es := NewEchoServer("127.0.0.1:18081") // Run the server for 1 second time.Sleep(1 * time.Second) // Close the server log.Println("Stopping echo server") es.stop() }
Dans ce code, la fonction serve termine gracieusement le serveur en retournant lorsqu'une valeur est reçue sur le canal terminé. La fonction principale montre comment démarrer le serveur, attendre les connexions, puis y mettre fin correctement. En utilisant un canal terminé, la gestion des erreurs est clairement séparée de la logique d'arrêt, ce qui donne un serveur plus maintenable et sans erreur.
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!