🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
#### 9.5 使用Zinx-V0.9完成应用程序 好了,现在我们基本上已经将全部的连接管理的功能集成到Zinx中了,接下来就需要测试一下链接管理模块是否可以使用了。 写一个服务端: > Server.go ```go package main import ( "fmt" "zinx/ziface" "zinx/znet" ) //ping test 自定义路由 type PingRouter struct { znet.BaseRouter } //Ping Handle func (this *PingRouter) Handle(request ziface.IRequest) { fmt.Println("Call PingRouter Handle") //先读取客户端的数据,再回写ping...ping...ping fmt.Println("recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData())) err := request.GetConnection().SendBuffMsg(0, []byte("ping...ping...ping")) if err != nil { fmt.Println(err) } } type HelloZinxRouter struct { znet.BaseRouter } //HelloZinxRouter Handle func (this *HelloZinxRouter) Handle(request ziface.IRequest) { fmt.Println("Call HelloZinxRouter Handle") //先读取客户端的数据,再回写ping...ping...ping fmt.Println("recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData())) err := request.GetConnection().SendBuffMsg(1, []byte("Hello Zinx Router V0.8")) if err != nil { fmt.Println(err) } } //创建连接的时候执行 func DoConnectionBegin(conn ziface.IConnection) { fmt.Println("DoConnecionBegin is Called ... ") err := conn.SendMsg(2, []byte("DoConnection BEGIN...")) if err != nil { fmt.Println(err) } } //连接断开的时候执行 func DoConnectionLost(conn ziface.IConnection) { fmt.Println("DoConneciotnLost is Called ... ") } func main() { //创建一个server句柄 s := znet.NewServer() //注册链接hook回调函数 s.SetOnConnStart(DoConnectionBegin) s.SetOnConnStop(DoConnectionLost) //配置路由 s.AddRouter(0, &PingRouter{}) s.AddRouter(1, &HelloZinxRouter{}) //开启服务 s.Serve() } ``` 我们这里注册了两个Hook函数一个是链接初始化之后`DoConnectionBegin()`和链接停止之前`DoConnectionLost()`。 `DoConnectionBegin()`会发给客户端一个消息2的文本,并且在服务端打印一个调试信息"DoConnecionBegin is Called ... " `DoConnectionLost()`在服务端打印一个调试信息"DoConneciotnLost is Called ... " 客户端: > Client.go ```go package main import ( "fmt" "io" "net" "time" "zinx/znet" ) /* 模拟客户端 */ func main() { fmt.Println("Client Test ... start") //3秒之后发起测试请求,给服务端开启服务的机会 time.Sleep(3 * time.Second) conn,err := net.Dial("tcp", "127.0.0.1:7777") if err != nil { fmt.Println("client start err, exit!") return } for { //发封包message消息 dp := znet.NewDataPack() msg, _ := dp.Pack(znet.NewMsgPackage(0,[]byte("Zinx V0.8 Client0 Test Message"))) _, err := conn.Write(msg) if err !=nil { fmt.Println("write error err ", err) return } //先读出流中的head部分 headData := make([]byte, dp.GetHeadLen()) _, err = io.ReadFull(conn, headData) //ReadFull 会把msg填充满为止 if err != nil { fmt.Println("read head error") break } //将headData字节流 拆包到msg中 msgHead, err := dp.Unpack(headData) if err != nil { fmt.Println("server unpack err:", err) return } if msgHead.GetDataLen() > 0 { //msg 是有data数据的,需要再次读取data数据 msg := msgHead.(*znet.Message) msg.Data = make([]byte, msg.GetDataLen()) //根据dataLen从io中读取字节流 _, err := io.ReadFull(conn, msg.Data) if err != nil { fmt.Println("server unpack data err:", err) return } fmt.Println("==> Recv Msg: ID=", msg.Id, ", len=", msg.DataLen, ", data=", string(msg.Data)) } time.Sleep(1*time.Second) } } ``` 代码不变。 启动服务端 ``` $go run Server.go ``` 启动客户端 ``` $go run Client.go ``` 服务端结果: ```bash $ go run Server.go Add api msgId = 0 Add api msgId = 1 [START] Server name: zinx v-0.8 demoApp,listenner at IP: 127.0.0.1, Port 7777 is starting [Zinx] Version: V0.4, MaxConn: 3, MaxPacketSize: 4096 start Zinx server zinx v-0.8 demoApp succ, now listenning... Worker ID = 9 is started. Worker ID = 5 is started. Worker ID = 6 is started. Worker ID = 7 is started. Worker ID = 8 is started. Worker ID = 1 is started. Worker ID = 0 is started. Worker ID = 2 is started. Worker ID = 3 is started. Worker ID = 4 is started. connection add to ConnManager successfully: conn num = 1 ---> CallOnConnStart.... DoConnecionBegin is Called ... [Writer Goroutine is running] [Reader Goroutine is running] Add ConnID= 0 request msgID= 0 to workerID= 0 Call PingRouter Handle recv from client : msgId= 0 , data= Zinx V0.8 Client0 Test Message Add ConnID= 0 request msgID= 0 to workerID= 0 Call PingRouter Handle recv from client : msgId= 0 , data= Zinx V0.8 Client0 Test Message Add ConnID= 0 request msgID= 0 to workerID= 0 Call PingRouter Handle recv from client : msgId= 0 , data= Zinx V0.8 Client0 Test Message Add ConnID= 0 request msgID= 0 to workerID= 0 Call PingRouter Handle recv from client : msgId= 0 , data= Zinx V0.8 Client0 Test Message Add ConnID= 0 request msgID= 0 to workerID= 0 Call PingRouter Handle recv from client : msgId= 0 , data= Zinx V0.8 Client0 Test Message read msg head error read tcp4 127.0.0.1:7777->127.0.0.1:49510: read: connection reset by peer Conn Stop()...ConnID = 0 ---> CallOnConnStop.... DoConneciotnLost is Called ... connection Remove ConnID= 0 successfully: conn num = 0 127.0.0.1:49510 [conn Reader exit!] 127.0.0.1:49510 [conn Writer exit!] ``` 客户端结果: ```bash $ go run Client0.go Client Test ... start ==> Recv Msg: ID= 2 , len= 21 , data= DoConnection BEGIN... ==> Recv Msg: ID= 0 , len= 18 , data= ping...ping...ping ==> Recv Msg: ID= 0 , len= 18 , data= ping...ping...ping ==> Recv Msg: ID= 0 , len= 18 , data= ping...ping...ping ==> Recv Msg: ID= 0 , len= 18 , data= ping...ping...ping ^Csignal: interrupt ``` 客户端创建成功,回调Hook已经执行,并且Conn被添加到ConnManager 中, conn num = 1, 当我们手动CTRL+C 关闭客户端的时候, 服务器ConnManager已经成功将Conn摘掉,conn num = 0. 同时服务端也打印出 conn停止之后的回调信息。