A) IServer增添路由添加功能

我们需要给IServer类,增加一个抽象方法AddRouter,目的也是让Zinx框架使用者,可以自定一个Router处理业务方法

zinx/ziface/irouter.go

package ziface

//定义服务器接口
type IServer interface{
    //启动服务器方法
    Start()
    //停止服务器方法
    Stop()
    //开启业务服务方法
    Serve()

    //新增:
    //路由功能:给当前服务注册一个路由业务方法,供处理 客户端连接 使用
    AddRouter(router IRouter)
}

B) Server类增添Router成员

有了抽象的方法,自然Server就要实现,并且还要添加一个Router成员.

zinx/znet/server.go

//iServer 接口实现,定义一个Server服务类
type Server struct {
    //服务器的名称
    Name string
    //tcp4 or other
    IPVersion string
    //服务绑定的IP地址
    IP string
    //服务绑定的端口
    Port int

    //新增:
    //当前Server由用户绑定的回调router,也就是Server注册的连接对应的处理业务
    Router ziface.IRouter
}

然后NewServer()方法, 初始化Server对象的方法也要加一个初始化成员

/*
  创建一个服务器句柄
 */
func NewServer (name string) ziface.IServer {
    s:= &Server {
        Name :name,
        IPVersion:"tcp4",
        IP:"0.0.0.0",
        Port:7777,

        Router: nil,
    }

    return s
}

C) Connection类绑定一个Router成员

zinx/znet/connection.go

type Connection struct {
    //当前连接的socket TCP套接字
    Conn *net.TCPConn
    //当前连接的ID 也可以称作为SessionID,ID全局唯一
    ConnID uint32
    //当前连接的关闭状态
    isClosed bool

    //新增:
    //该连接的处理方法router
    Router  ziface.IRouter

    //告知该连接已经退出/停止的channel
    ExitBuffChan chan bool
}

D) 在Connection调用注册的Router处理业务

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  {
        //读取我们最大的数据到buf中
        buf := make([]byte, 512)
        _, err := c.Conn.Read(buf)
        if err != nil {
            fmt.Println("recv buf err ", err)
            c.ExitBuffChan <- true
            continue
        }
        //得到当前客户端请求的Request数据
        req := Request{
            conn:c,
            data:buf,
        }

        //新增:
        //从路由Routers 中找到注册绑定Conn的对应Handle
        go func (request ziface.IRequest) {
            //执行注册的路由方法
            c.Router.PreHandle(request)
            c.Router.Handle(request)
            c.Router.PostHandle(request)
        }(&req)
    }
}

这里我们在conn读取完客户端数据之后,将数据和conn封装到一个Request中,作为Router的输入数据

然后我们开启一个goroutine去调用给Zinx框架注册好的路由业务。