Próbowałem znaleźć sposób, aby zatrzymać serwer nasłuchujący w Go z wdziękiem. Ponieważ listen.Accept
blokuje, konieczne jest zamknięcie gniazda nasłuchu, aby zasygnalizować koniec, ale nie mogę stwierdzić tego błędu z wyjątkiem innych błędów, ponieważ odpowiedni błąd nie jest eksportowany.Jak zatrzymać serwer nasłuchujący w Go
Czy mogę lepiej niż to? Zobacz FIXME
w poniższym kodzie w serve()
package main
import (
"io"
"log"
"net"
"time"
)
// Echo server struct
type EchoServer struct {
listen net.Listener
done chan bool
}
// 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()
// FIXME I'd like to detect "use of closed network connection" here
// FIXME but it isn't exported from net
if err != nil {
log.Printf("Accept failed: %v", err)
break
}
go es.respond(conn.(*net.TCPConn))
}
es.done <- true
}
// Stop the server by closing the listening listen
func (es *EchoServer) stop() {
es.listen.Close()
<-es.done
}
// 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,
done: make(chan bool),
}
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()
}
Drukuje
2012/11/16 12:53:35 Starting echo server
2012/11/16 12:53:36 Stopping echo server
2012/11/16 12:53:36 Accept failed: accept tcp 127.0.0.1:18081: use of closed network connection
Chciałbym, aby ukryć komunikat Accept failed
, ale oczywiście nie chcę, aby zamaskować inne błędy Accept
może zgłosić. Mógłbym oczywiście zajrzeć do testu błędu dla use of closed network connection
, ale to byłoby naprawdę brzydkie. Mogłabym ustawić flagę mówiącą, że mam zamiar zamknąć i zignorować błędy, jeśli to było ustawione. Przypuszczam - Czy istnieje lepszy sposób?
To zgrabny pomysł! Istnieje warunek wyścigowy z rzeczywistymi połączeniami, które jednak trzeba obejść. –
Tak, prawda. Możesz spróbować odwrotności tego - zawsze mieć to pojedyncze wewnętrzne połączenie od początku i używać go jako kanału kontrolnego. –