A) IServer增添路由添加功能

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

zinx/ziface/irouter.go

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

B) Server类增添Router成员

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

zinx/znet/server.go

  1. //iServer 接口实现,定义一个Server服务类
  2. type Server struct {
  3. //服务器的名称
  4. Name string
  5. //tcp4 or other
  6. IPVersion string
  7. //服务绑定的IP地址
  8. IP string
  9. //服务绑定的端口
  10. Port int
  11. //当前Server由用户绑定的回调router,也就是Server注册的链接对应的处理业务
  12. Router ziface.IRouter
  13. }

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

  1. /*
  2. 创建一个服务器句柄
  3. */
  4. func NewServer (name string) ziface.IServer {
  5. s:= &Server {
  6. Name :name,
  7. IPVersion:"tcp4",
  8. IP:"0.0.0.0",
  9. Port:7777,
  10. Router: nil,
  11. }
  12. return s
  13. }

C) Connection类绑定一个Router成员

zinx/znet/connection.go

  1. type Connection struct {
  2. //当前连接的socket TCP套接字
  3. Conn *net.TCPConn
  4. //当前连接的ID 也可以称作为SessionID,ID全局唯一
  5. ConnID uint32
  6. //当前连接的关闭状态
  7. isClosed bool
  8. //该连接的处理方法router
  9. Router ziface.IRouter
  10. //告知该链接已经退出/停止的channel
  11. ExitBuffChan chan bool
  12. }

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

zinx/znet/connection.go

  1. func (c *Connection) StartReader() {
  2. fmt.Println("Reader Goroutine is running")
  3. defer fmt.Println(c.RemoteAddr().String(), " conn reader exit!")
  4. defer c.Stop()
  5. for {
  6. //读取我们最大的数据到buf中
  7. buf := make([]byte, 512)
  8. _, err := c.Conn.Read(buf)
  9. if err != nil {
  10. fmt.Println("recv buf err ", err)
  11. c.ExitBuffChan <- true
  12. continue
  13. }
  14. //得到当前客户端请求的Request数据
  15. req := Request{
  16. conn:c,
  17. data:buf,
  18. }
  19. //从路由Routers 中找到注册绑定Conn的对应Handle
  20. go func (request ziface.IRequest) {
  21. //执行注册的路由方法
  22. c.Router.PreHandle(request)
  23. c.Router.Handle(request)
  24. c.Router.PostHandle(request)
  25. }(&req)
  26. }
  27. }

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

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