首先iserverAddRouter()的接口要稍微改一下,增添MsgId参数

    zinx/ziface/iserver.go

    1. package ziface
    2. //定义服务器接口
    3. type IServer interface{
    4. //启动服务器方法
    5. Start()
    6. //停止服务器方法
    7. Stop()
    8. //开启业务服务方法
    9. Serve()
    10. //路由功能:给当前服务注册一个路由业务方法,供客户端链接处理使用
    11. AddRouter(msgId uint32, router IRouter)
    12. }

    其次,Server类中 之前有一个Router成员 ,代表唯一的处理方法,现在应该替换成MsgHandler成员

    zinx/znet/server.go

    type Server struct {
        //服务器的名称
        Name string
        //tcp4 or other
        IPVersion string
        //服务绑定的IP地址
        IP string
        //服务绑定的端口
        Port int
        //当前Server的消息管理模块,用来绑定MsgId和对应的处理方法
        msgHandler ziface.IMsgHandle
    }
    

    初始化Server自然也要更正,增加msgHandler初始化

    /*
      创建一个服务器句柄
     */
    func NewServer () ziface.IServer {
        utils.GlobalObject.Reload()
    
        s:= &Server {
            Name :utils.GlobalObject.Name,
            IPVersion:"tcp4",
            IP:utils.GlobalObject.Host,
            Port:utils.GlobalObject.TcpPort,
            msgHandler: NewMsgHandle(), //msgHandler 初始化
        }
        return s
    }
    

    然后当Server在处理conn请求业务的时候,创建conn的时候也需要把msgHandler作为参数传递给Connection对象

    //...
    dealConn := NewConntion(conn, cid, s.msgHandler)
    //...
    

    那么接下来就是Connection对象了。固然在Connection对象中应该有MsgHandler的成员,来查找消息对应的回调路由方法

    zinx/znet/connection.go

    type Connection struct {
        //当前连接的socket TCP套接字
        Conn *net.TCPConn
        //当前连接的ID 也可以称作为SessionID,ID全局唯一
        ConnID uint32
        //当前连接的关闭状态
        isClosed bool
        //消息管理MsgId和对应处理方法的消息管理模块
        MsgHandler ziface.IMsgHandle
        //告知该链接已经退出/停止的channel
        ExitBuffChan chan bool
    }
    
    //创建连接的方法
    func NewConntion(conn *net.TCPConn, connID uint32, msgHandler ziface.IMsgHandle) *Connection{
        c := &Connection{
            Conn:     conn,
            ConnID:   connID,
            isClosed: false,
            MsgHandler: msgHandler,
            ExitBuffChan: make(chan bool, 1),
        }
    
        return c
    }
    

    最后,在conn已经拆包之后,需要调用路由业务的时候,我们只需要让conn调用MsgHandler中的DoMsgHander()方法就好了

    zinx/znet/connection.go

    func (c *Connection) StartReader() {
        fmt.Println("[Reader Goroutine is running]")
        defer fmt.Println(c.RemoteAddr().String(), "[conn Reader exit!]")
        defer c.Stop()
    
        for  {
            // 创建拆包解包的对象
            dp := NewDataPack()
    
            //读取客户端的Msg head
            headData := make([]byte, dp.GetHeadLen())
            if _, err := io.ReadFull(c.GetTCPConnection(), headData); err != nil {
                fmt.Println("read msg head error ", err)
                break
            }
    
            //拆包,得到msgid 和 datalen 放在msg中
            msg , err := dp.Unpack(headData)
            if err != nil {
                fmt.Println("unpack error ", err)
                break
            }
    
            //根据 dataLen 读取 data,放在msg.Data中
            var data []byte
            if msg.GetDataLen() > 0 {
                data = make([]byte, msg.GetDataLen())
                if _, err := io.ReadFull(c.GetTCPConnection(), data); err != nil {
                    fmt.Println("read msg data error ", err)
                    continue
                }
            }
            msg.SetData(data)
    
            //得到当前客户端请求的Request数据
            req := Request{
                conn:c,
                msg:msg,
            }
            //从绑定好的消息和对应的处理方法中执行对应的Handle方法
            go c.MsgHandler.DoMsgHandler(&req)
        }
    }
    

    好了,大功告成,我们来测试一下Zinx的多路由设置功能吧。