zinx
zinx copied to clipboard
我需要手动控制服务器的开启关闭, 但Stop()后, tcplistener不被关闭
对zinx/examples/zinx_server中的main.go文件中的main函数小小地修改,如下
// zinx/examples/zinx_server/main.go
func main() {
//创建一个server句柄
s := znet.NewServer()
//注册链接hook回调函数
s.SetOnConnStart(DoConnectionBegin)
s.SetOnConnStop(DoConnectionLost)
//配置路由
s.AddRouter(0, &zrouter.PingRouter{})
s.AddRouter(1, &zrouter.HelloZinxRouter{})
//开启服务
s.Start()
time.Sleep(time.Second * 10)
s.Stop()
time.Sleep(time.Second * 10)
s.Serve()
}
运行时终端打印如下
██
▀▀
████████ ████ ██▄████▄ ▀██ ██▀
▄█▀ ██ ██▀ ██ ████
▄█▀ ██ ██ ██ ▄██▄
▄██▄▄▄▄▄ ▄▄▄██▄▄▄ ██ ██ ▄█▀▀█▄
▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀ ▀▀▀
┌───────────────────────────────────────────────────┐
│ [Github] https://github.com/aceld │
│ [tutorial] https://www.kancloud.cn/aceld/zinx │
└───────────────────────────────────────────────────┘
[Zinx] Version: V1.0, MaxConn: 3, MaxPacketSize: 4096
Add api msgID = 0
Add api msgID = 1
[START] Server name: zinx server Demo,listenner at IP: 127.0.0.1, Port 8999 is starting
Worker ID = 0 is started.
Worker ID = 1 is started.
Worker ID = 3 is started.
Worker ID = 2 is started.
Worker ID = 4 is started.
Worker ID = 5 is started.
Worker ID = 6 is started.
Worker ID = 7 is started.
Worker ID = 8 is started.
Worker ID = 9 is started.
start Zinx server zinx server Demo succ, now listenning...
[STOP] Zinx server , name zinx server Demo
Clear All Connections successfully: conn num = 0
[START] Server name: zinx server Demo,listenner at IP: 127.0.0.1, Port 8999 is starting
Worker ID = 0 is started.
Worker ID = 4 is started.
Worker ID = 1 is started.
Worker ID = 2 is started.
Worker ID = 3 is started.
Worker ID = 5 is started.
Worker ID = 7 is started.
Worker ID = 8 is started.
Worker ID = 9 is started.
panic: listen tcp4 127.0.0.1:8999: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.
goroutine 34 [running]:
github.com/aceld/zinx/znet.(*Server).Start.func1()
D:/GOPATH/pkg/mod/github.com/aceld/[email protected]/znet/server.go:88 +0x3ec
created by github.com/aceld/zinx/znet.(*Server).Start
D:/GOPATH/pkg/mod/github.com/aceld/[email protected]/znet/server.go:74 +0x126
exit status 2
可能是因为Stop方法没有关闭listenner, 所以导致这个问题
我不确定我的修复建议是否可行:
- 在Server里维护一个信号管道c,开一个新的goroutine不断accept连接,调用Stop()会向c中发信息, Start 携程负责阻塞等待这个信息, 并关闭listenner, 下面是伪代码
func (s *Server) Start() {
go func() {
tcpAddr, err := net.ResolveTCPAddr(s.TCPVersion, fmt.Sprintf("%v:%v", s.IP, s.Port))
if err != nil {
panic(err)
}
l, err := net.ListenTCP(s.TCPVersion, tcpAddr)
if err != nil {
panic(err)
}
log.Println("server started")
go func() {
for {
var cid uint32 = 0
c, err := l.AcceptTCP()
if err != nil {
if isListennerClosedErr(err) {
log.Println("server had been stopped, accepter exiting")
return
}
log.Println("failed to accept a connection, err:", err)
continue
}
NewConnection(c, cid, s).Start()
cid++
}
}()
select {
case <-s.StopChan:
if err := l.Close(); err != nil {
log.Println("failed to close tcp listenner, err:", err)
}
}
}()
}
#145