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

A)ConnManager集成到Server中

现在需要将ConnManager添加到Server

zinx/znet/server.go

//iServer 接口实现,定义一个Server服务类
type Server struct {
    //服务器的名称
    Name string
    //tcp4 or other
    IPVersion string
    //服务绑定的IP地址
    IP string
    //服务绑定的端口
    Port int
    //当前Server的消息管理模块,用来绑定MsgId和对应的处理方法
    msgHandler ziface.IMsgHandle
    //当前Server的链接管理器
    ConnMgr ziface.IConnManager
}

/*
  创建一个服务器句柄
 */
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(),
        ConnMgr:NewConnManager(),  //创建ConnManager
    }
    return s
}

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

zinx/ziface/iserver.go

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

zinx/znet/server.go

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

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

zinx/znet/connection.go

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

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

zinx/znet/connection.go

//创建连接的方法
func NewConntion(server ziface.IServer, conn *net.TCPConn, connID uint32, msgHandler ziface.IMsgHandle) *Connection{
    //初始化Conn属性
    c := &Connection{
        TcpServer:server,    //将隶属的server传递进来
        Conn:     conn,
        ConnID:   connID,
        isClosed: false,
        MsgHandler: msgHandler,
        ExitBuffChan: make(chan bool, 1),
        msgChan:make(chan []byte),
        msgBuffChan:make(chan []byte, utils.GlobalObject.MaxMsgChanLen),
    }

    //将新创建的Conn添加到链接管理中
    c.TcpServer.GetConnMgr().Add(c)   //将当前新创建的连接添加到ConnManager中 
    return c
}
C) Server中添加链接数量的判断

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

zinx/znet/server.go

//开启网络服务
func (s *Server) Start() {
    fmt.Printf("[START] Server name: %s,listenner at IP: %s, Port %d is starting\n", s.Name, s.IP, s.Port)
    fmt.Printf("[Zinx] Version: %s, MaxConn: %d, MaxPacketSize: %d\n",
        utils.GlobalObject.Version,
        utils.GlobalObject.MaxConn,
        utils.GlobalObject.MaxPacketSize)

    //开启一个go去做服务端Linster业务
    go func() {
        // ....

        //3 启动server网络连接业务
        for {
            //3.1 阻塞等待客户端建立连接请求
            conn, err := listenner.AcceptTCP()
            if err != nil {
                fmt.Println("Accept err ", err)
                continue
            }

            //=============
            //3.2 设置服务器最大连接控制,如果超过最大连接,那么则关闭此新的连接
            if s.ConnMgr.Len() >= utils.GlobalObject.MaxConn {
                conn.Close()
                continue
            }
            //=============

            //3.3 处理该新连接请求的 业务 方法, 此时应该有 handler 和 conn是绑定的
            dealConn := NewConntion(s, conn, cid, s.msgHandler)
            cid ++

            //3.4 启动当前链接的处理业务
            go dealConn.Start()
        }
    }()
}

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

D) 连接的删除

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

zinx/znet/connecion.go

func (c *Connection) Stop() {
    fmt.Println("Conn Stop()...ConnID = ", c.ConnID)
    //如果当前链接已经关闭
    if c.isClosed == true {
        return
    }
    c.isClosed = true


    // 关闭socket链接
    c.Conn.Close()
    //关闭Writer Goroutine
    c.ExitBuffChan <- true

    //将链接从连接管理器中删除
    c.TcpServer.GetConnMgr().Remove(c)  //删除conn从ConnManager中

    //关闭该链接全部管道
    close(c.ExitBuffChan)
    close(c.msgBuffChan)
}

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

zinx/znet/server.go

func (s *Server) Stop() {
    fmt.Println("[STOP] Zinx server , name " , s.Name)

    //将其他需要清理的连接信息或者其他信息 也要一并停止或者清理
    s.ConnMgr.ClearConn()
}

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

results matching ""

    No results matching ""