我一直试图找到一种方法来优雅地停止Go中的监听服务器。因为listen.Accept阻塞了,所以有必要关闭侦听套接字以发出结束信号,但由于没有导出相关错误,因此我无法分辨该错误以及其他任何错误。
listen.Accept
我可以做得更好吗?请参阅FIXME下面的代码serve()
FIXME
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() }
此打印
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
我想隐藏Accept failed消息,但是显然我不想掩盖Accept可以报告的其他错误。我当然可以在错误测试中进行查找,use of closed network connection但这确实很难看。我可以设置一个标志,说如果要设置,我将要关闭并忽略错误-有更好的方法吗?
Accept failed
Accept
use of closed network connection
accept()调用后立即在循环中检查一些“是否该停止了”标志,然后从中将其翻转main,然后 连接 到侦听端口以获取服务器套接字“未卡住”。这非常类似于旧的“自管技巧”。
accept()
main