• 9.2 链接管理模块集成到Zinx中
    • A)ConnManager集成到Server中
    • B) 链接的添加
    • C) Server中添加链接数量的判断
    • D) 连接的删除

    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之中了。