6.2 Zinx-V0.6代码实现

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

zinx/ziface/iserver.go

package ziface

//定义服务器接口
type IServer interface{
    //启动服务器方法
    Start()
    //停止服务器方法
    Stop()
    //开启业务服务方法
    Serve()
    //路由功能:给当前服务注册一个路由业务方法,供客户端链接处理使用
    AddRouter(msgId uint32, router IRouter)
}

其次,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的多路由设置功能吧。

results matching ""

    No results matching ""