9.2 链接管理模块集成到Zinx中

A)ConnManager集成到Server中

现在需要将ConnManager添加到Server

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的消息管理模块,用来绑定MsgId和对应的处理方法
  12. msgHandler ziface.IMsgHandle
  13. //当前Server的链接管理器
  14. ConnMgr ziface.IConnManager
  15. }
  16. /*
  17. 创建一个服务器句柄
  18. */
  19. func NewServer () ziface.IServer {
  20. utils.GlobalObject.Reload()
  21. s:= &Server {
  22. Name :utils.GlobalObject.Name,
  23. IPVersion:"tcp4",
  24. IP:utils.GlobalObject.Host,
  25. Port:utils.GlobalObject.TcpPort,
  26. msgHandler: NewMsgHandle(),
  27. ConnMgr:NewConnManager(), //创建ConnManager
  28. }
  29. return s
  30. }

那么,既然server具备了ConnManager成员,在获取的时候需要给抽象层提供一个获取ConnManager方法

zinx/ziface/iserver.go

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

zinx/znet/server.go

  1. //得到链接管理
  2. func (s *Server) GetConnMgr() ziface.IConnManager {
  3. return s.ConnMgr
  4. }

因为我们现在在server中有链接的管理,有的时候conn也需要得到这个ConnMgr的使用权,那么我们需要将ServerConnection建立能够互相索引的关系,我们在Connection中,添加Server当前conn隶属的server句柄。

zinx/znet/connection.go

  1. type Connection struct {
  2. //当前Conn属于哪个Server
  3. TcpServer ziface.IServer //当前conn属于哪个server,在conn初始化的时候添加即可
  4. //当前连接的socket TCP套接字
  5. Conn *net.TCPConn
  6. //当前连接的ID 也可以称作为SessionID,ID全局唯一
  7. ConnID uint32
  8. //当前连接的关闭状态
  9. isClosed bool
  10. //消息管理MsgId和对应处理方法的消息管理模块
  11. MsgHandler ziface.IMsgHandle
  12. //告知该链接已经退出/停止的channel
  13. ExitBuffChan chan bool
  14. //无缓冲管道,用于读、写两个goroutine之间的消息通信
  15. msgChan chan []byte
  16. //有关冲管道,用于读、写两个goroutine之间的消息通信
  17. msgBuffChan chan []byte
  18. }
B) 链接的添加

那么我们什么选择将创建好的连接添加到ConnManager中呢,这里我们选择在初始化一个新链接的时候,加进来就好了

zinx/znet/connection.go

  1. //创建连接的方法
  2. func NewConntion(server ziface.IServer, conn *net.TCPConn, connID uint32, msgHandler ziface.IMsgHandle) *Connection{
  3. //初始化Conn属性
  4. c := &Connection{
  5. TcpServer:server, //将隶属的server传递进来
  6. Conn: conn,
  7. ConnID: connID,
  8. isClosed: false,
  9. MsgHandler: msgHandler,
  10. ExitBuffChan: make(chan bool, 1),
  11. msgChan:make(chan []byte),
  12. msgBuffChan:make(chan []byte, utils.GlobalObject.MaxMsgChanLen),
  13. }
  14. //将新创建的Conn添加到链接管理中
  15. c.TcpServer.GetConnMgr().Add(c) //将当前新创建的连接添加到ConnManager中
  16. return c
  17. }
C) Server中添加链接数量的判断

在server的Start()方法中,在Accept与客户端链接建立成功后,可以直接对链接的个数做一个判断

zinx/znet/server.go

  1. //开启网络服务
  2. func (s *Server) Start() {
  3. fmt.Printf("[START] Server name: %s,listenner at IP: %s, Port %d is starting\n", s.Name, s.IP, s.Port)
  4. fmt.Printf("[Zinx] Version: %s, MaxConn: %d, MaxPacketSize: %d\n",
  5. utils.GlobalObject.Version,
  6. utils.GlobalObject.MaxConn,
  7. utils.GlobalObject.MaxPacketSize)
  8. //开启一个go去做服务端Linster业务
  9. go func() {
  10. // ....
  11. //3 启动server网络连接业务
  12. for {
  13. //3.1 阻塞等待客户端建立连接请求
  14. conn, err := listenner.AcceptTCP()
  15. if err != nil {
  16. fmt.Println("Accept err ", err)
  17. continue
  18. }
  19. //=============
  20. //3.2 设置服务器最大连接控制,如果超过最大连接,那么则关闭此新的连接
  21. if s.ConnMgr.Len() >= utils.GlobalObject.MaxConn {
  22. conn.Close()
  23. continue
  24. }
  25. //=============
  26. //3.3 处理该新连接请求的 业务 方法, 此时应该有 handler 和 conn是绑定的
  27. dealConn := NewConntion(s, conn, cid, s.msgHandler)
  28. cid ++
  29. //3.4 启动当前链接的处理业务
  30. go dealConn.Start()
  31. }
  32. }()
  33. }

当然,我们应该在配置文件zinx.json或者在GlobalObject全局配置中,定义好我们期望的连接的最大数目限制MaxConn

D) 连接的删除

我们应该在连接停止的时候,将该连接从ConnManager中删除,所以在connectionStop()方法中添加。

zinx/znet/connecion.go

  1. func (c *Connection) Stop() {
  2. fmt.Println("Conn Stop()...ConnID = ", c.ConnID)
  3. //如果当前链接已经关闭
  4. if c.isClosed == true {
  5. return
  6. }
  7. c.isClosed = true
  8. // 关闭socket链接
  9. c.Conn.Close()
  10. //关闭Writer Goroutine
  11. c.ExitBuffChan <- true
  12. //将链接从连接管理器中删除
  13. c.TcpServer.GetConnMgr().Remove(c) //删除conn从ConnManager中
  14. //关闭该链接全部管道
  15. close(c.ExitBuffChan)
  16. close(c.msgBuffChan)
  17. }

当然,我们也应该在server停止的时候,将全部的连接清空

zinx/znet/server.go

  1. func (s *Server) Stop() {
  2. fmt.Println("[STOP] Zinx server , name " , s.Name)
  3. //将其他需要清理的连接信息或者其他信息 也要一并停止或者清理
  4. s.ConnMgr.ClearConn()
  5. }

现在我们已经将连接管理成功的集成到了Zinx之中了。