前言
之前在已经给Zinx配置了路由模式,但是之前的Zinx只能绑定一个路由的处理业务方法 显然这是无法满足基本的服务器需求,需要给Zinx添加多路由的方案 查看之前的Server定义,路由Router只有一个
type Server struct {
Name string
IPVersion string
IP string
Port int
Router ziface. IRouter
}
一、实现思路
二、消息管理模块实现
1 - 添加接口ziface/imsgHandler.go
package ziface
type IMsgHandle interface {
DoMsgHandler ( request IRequest)
AddRouter ( msgID uint32 , router IRouter)
}
2 - 实现接口znet/msgHandler.go
package znet
import (
"fmt"
"strconv"
"zinx/ziface"
)
type MsgHandle struct {
Apis map [ uint32 ] ziface. IRouter
}
func NewMsgHandle ( ) * MsgHandle {
return & MsgHandle{
Apis: make ( map [ uint32 ] ziface. IRouter) ,
}
}
func ( mh * MsgHandle) DoMsgHandler ( request ziface. IRequest) {
handler, ok := mh. Apis[ request. GetMsgID ( ) ]
if ! ok {
fmt. Println ( "api msgID = " , request. GetMsgID ( ) , " is NOT FOUND! Need Register!" )
}
handler. PreHandle ( request)
handler. Handle ( request)
handler. PostHandle ( request)
}
func ( mh * MsgHandle) AddRouter ( msgID uint32 , router ziface. IRouter) {
if _ , ok := mh. Apis[ msgID] ; ok {
panic ( "repeat api , msgID = " + strconv. Itoa ( int ( msgID) ) )
}
mh. Apis[ msgID] = router
fmt. Println ( "Add api MsgID = " , msgID, " succ!" )
}
三、Zinx集成消息管理模块
1 - znet/server.go
Server结构体将之前的Handle替换成MsgHandler
type Server struct {
Name string
IPVersion string
IP string
Port int
MsgHandler ziface. IMsgHandle
}
AddRouter方法修改成MsgHandler.AddRouter
func ( s * Server) AddRouter ( msgID uint32 , router ziface. IRouter) {
s. MsgHandler. AddRouter ( msgID, router)
fmt. Println ( "Add Router Succ!!" )
}
func NewServer ( name string ) ziface. IServer {
s := & Server{
Name: utils. GlobalObject. Name,
IPVersion: "tcp4" ,
IP: utils. GlobalObject. Host,
Port: utils. GlobalObject. TcpPort,
MsgHandler: NewMsgHandle ( ) ,
}
return s
}
func ( s * Server) Start ( ) {
...
dealConn := NewConnection ( conn, cid, s. MsgHandler)
cid++
...
}
2 - ziface/iserver.go
package ziface
type IServer interface {
Start ( )
Stop ( )
Serve ( )
AddRouter ( uint32 , IRouter)
}
3 - znet/connection.go
type Connection struct {
...
MsgHandler ziface. IMsgHandle
}
func NewConnection ( conn * net. TCPConn, connID uint32 , msgHandler ziface. IMsgHandle) * Connection {
c := & Connection{
Conn: conn,
ConnID: connID,
MsgHandler: msgHandler,
isClosed: false ,
ExitChan: make ( chan bool , 1 ) ,
}
return c
}
func ( c * Connection) StartReader ( ) {
...
go c. MsgHandler. DoMsgHandler ( & req)
}
}
四、测试类实现
1 - 测试Server.go
多Router :0 —— PingRouter;1 —— HelloZinxRouter
package main
import (
"fmt"
"zinx/ziface"
"zinx/znet"
)
type PingRouter struct {
znet. BaseRouter
}
func ( this * PingRouter) Handle ( request ziface. IRequest) {
fmt. Println ( "Call PingRouter Handle..." )
fmt. Println ( "recv from client: msgID = " , request. GetMsgID ( ) ,
", data = " , string ( request. GetData ( ) ) )
err := request. GetConnection ( ) . SendMsg ( 200 , [ ] byte ( "ping...ping...ping" ) )
if err != nil {
fmt. Println ( err)
}
}
type HelloZinxRouter struct {
znet. BaseRouter
}
func ( this * HelloZinxRouter) Handle ( request ziface. IRequest) {
fmt. Println ( "Call HelloZinxRouter Handle..." )
fmt. Println ( "recv from client: msgID = " , request. GetMsgID ( ) ,
", data = " , string ( request. GetData ( ) ) )
err := request. GetConnection ( ) . SendMsg ( 201 , [ ] byte ( "Hello Welcome to Zinx!!" ) )
if err != nil {
fmt. Println ( err)
}
}
func main ( ) {
s := znet. NewServer ( "[zinx V0.6]" )
s. AddRouter ( 0 , & PingRouter{ } )
s. AddRouter ( 1 , & HelloZinxRouter{ } )
s. Serve ( )
}
2 - 测试Client
多Client :Client0.go —— 发送0消息;Client1 —— 发送1消息Client0
package main
import (
"fmt"
"io"
"net"
"time"
"zinx/znet"
)
func main ( ) {
fmt. Println ( "client0 start..." )
time. Sleep ( 1 * time. Second)
conn, err := net. Dial ( "tcp" , "127.0.0.1:8999" )
if err != nil {
fmt. Println ( "client start err, exit!" )
return
}
for {
dp := znet. NewDataPack ( )
binaryMsg, err := dp. Pack ( znet. NewMsgPackage ( 0 , [ ] byte ( "Zinx client0 Test Message" ) ) )
if err != nil {
fmt. Println ( "Pack error:" , err)
return
}
if _ , err := conn. Write ( binaryMsg) ; err != nil {
fmt. Println ( "write error" , err)
return
}
binaryHead := make ( [ ] byte , dp. GetHeadLen ( ) )
if _ , err := io. ReadFull ( conn, binaryHead) ; err != nil {
fmt. Println ( "read head error " , err)
break
}
msgHead, err := dp. Unpack ( binaryHead)
if err != nil {
fmt. Println ( "client unpack msgHead error " , err)
break
}
if msgHead. GetMsgLen ( ) > 0 {
msg := msgHead. ( * znet. Message)
msg. Data = make ( [ ] byte , msg. GetMsgLen ( ) )
if _ , err := io. ReadFull ( conn, msg. Data) ; err != nil {
fmt. Println ( "read msg data error , " , err)
return
}
fmt. Println ( "---> Recv Server Msg : ID = " , msg. Id, ", len = " , msg. DataLen, ", data = " , string ( msg. Data) )
}
time. Sleep ( 1 * time. Second)
}
}
package main
import (
"fmt"
"io"
"net"
"time"
"zinx/znet"
)
func main ( ) {
fmt. Println ( "client1 start..." )
time. Sleep ( 1 * time. Second)
conn, err := net. Dial ( "tcp" , "127.0.0.1:8999" )
if err != nil {
fmt. Println ( "client start err, exit!" )
return
}
for {
dp := znet. NewDataPack ( )
binaryMsg, err := dp. Pack ( znet. NewMsgPackage ( 1 , [ ] byte ( "Zinx client1 Test Message" ) ) )
if err != nil {
fmt. Println ( "Pack error:" , err)
return
}
if _ , err := conn. Write ( binaryMsg) ; err != nil {
fmt. Println ( "write error" , err)
return
}
binaryHead := make ( [ ] byte , dp. GetHeadLen ( ) )
if _ , err := io. ReadFull ( conn, binaryHead) ; err != nil {
fmt. Println ( "read head error " , err)
break
}
msgHead, err := dp. Unpack ( binaryHead)
if err != nil {
fmt. Println ( "client unpack msgHead error " , err)
break
}
if msgHead. GetMsgLen ( ) > 0 {
msg := msgHead. ( * znet. Message)
msg. Data = make ( [ ] byte , msg. GetMsgLen ( ) )
if _ , err := io. ReadFull ( conn, msg. Data) ; err != nil {
fmt. Println ( "read msg data error , " , err)
return
}
fmt. Println ( "---> Recv Server Msg : ID = " , msg. Id, ", len = " , msg. DataLen, ", data = " , string ( msg. Data) )
}
time. Sleep ( 1 * time. Second)
}
}
3 - 测试截图
五、项目结构
六、完整源码
点击下载zinxV0.6