如何停止Go中的Listening服务器 [英] How do I stop a Listening server in Go
问题描述
我一直在试图找到一种方法来优雅地停止Go中的侦听服务器。由于 listen.Accept
阻塞,因此有必要关闭监听套接字来告知结束,但除了其他错误之外,我无法确定该错误,因为相关错误不是' t出口。
我能做得更好吗?在 serve()
<$的代码中见
FIXME
io
log
net
time
)
//回声服务器结构
类型EchoServer结构{
监听net.Listener
完成chan bool
}
//响应传入连接
//
//写入连接的地址echo
func(es * EchoServer)respond(remote * net.TCPConn){
defer remote.Close()
_,err:= io.Copy(remote,remote)
if err!= nil {
log.Printf(Error:%s, err)
//监听传入连接
func(es * EchoServer)serve(){
for {
conn,err:= es.listen.Accept()
// FIXME我想在这里检测使用封闭网络连接
// FIXME,但它不会从net $ b导出$ b if err!= nil {
log.Printf(Accept failed:%v,err)
break
去es.respond(conn。(* net.TCPConn))
}
es.done< - true
}
//关闭监听来停止服务器
func(es * EchoServer)stop(){
es.listen.Close()
<-es。完成
$ b $ //创建一个新的回显服务器
func NewEchoServer(地址字符串)* EchoServer {
listen,err:= net.Listen(tcp ,地址)
if err!= nil {
log.Fatalf(无法打开监听套接字:%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)
//运行服务器1秒
time.Sleep(1 * time.Second)
//关闭服务器
log.Println(停止echo服务器)
es.stop()
}
打印
2012/11/16 12:53:35启动回显服务器
2012/11/16 12:53:36停止回显服务器
2012/11/16 12:53:36接受失败:接受TCP 127.0.0.1:18081:使用封闭的网络连接
我想隐藏接受失败
消息,但显然我不想掩盖其他错误接受
可以报告。我当然可以看看使用封闭网络连接
的错误测试,但那会非常难看。我可以设置一个标志,说我即将关闭并忽略错误,如果设置了,我想 - 有没有更好的方法?
在 accept()
调用之后,检查循环中的一些是时候停止标志,然后将它从 main
,然后将 connect 连接到您的监听端口,以使服务器套接字未卡住。这与旧的自我推销技巧非常相似。
I've been trying to find a way to stop a listening server in Go gracefully. Because listen.Accept
blocks it is necessary to close the listening socket to signal the end, but I can't tell that error apart from any other errors as the relevant error isn't exported.
Can I do better than this? See FIXME
in the code below in 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()
}
This prints
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
I'd like to hide the Accept failed
message, but obviously I don't want to mask other errors Accept
can report. I could of course look in the error test for use of closed network connection
but that would be really ugly. I could set a flag saying I'm about to close and ignore errors if that was set I suppose - Is there a better way?
Check some "is it time to stop" flag in your loop right after the accept()
call, then flip it from your main
, then connect to your listening port to get server socket "un-stuck". This is very similar to the old "self-pipe trick".
这篇关于如何停止Go中的Listening服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!