package znet import ( "fmt" "go-study/zinx/ziface" "net" ) type Connection struct { // 该连接的 TCP Socket 套接字 Conn *net.TCPConn // 连接 ID,全局唯一 ConnID uint32 // 该连接的关闭状态 IsClosed bool // 该连接的处理方法 Router Router ziface.IRouter // 该连接的退出消息通知 channel ExitBuffChan chan struct{} } // NewConnection 创建连接的方法 func NewConnection(conn *net.TCPConn, connID uint32, router ziface.IRouter) ziface.IConnection { return &Connection{ Conn: conn, ConnID: connID, IsClosed: false, Router: router, ExitBuffChan: make(chan struct{}, 1), } } // StartReader 处理连接读数据的业务方法 func (c *Connection) StartReader() { fmt.Println("Reader Goroutine is running") defer fmt.Println("connID =", c.ConnID, "Reader is exit, remote addr is", c.RemoteAddr().String()) defer c.Stop() for { // 读取客户端数据到buf中,最大512字节 buf := make([]byte, 512) cnt, err := c.Conn.Read(buf) if err != nil { fmt.Println("recv buf err", err) c.ExitBuffChan <- struct{}{} continue } req := Request{ conn: c, data: buf[:cnt], } // 从路由中找到注册绑定的 Conn 对应的 router 调用 go func(request ziface.IRequest) { // 执行注册的路由方法 c.Router.PreHandle(request) c.Router.Handle(request) c.Router.PostHandle(request) }(&req) } } // Start 启动连接,让当前连接开始工作 func (c *Connection) Start() { // 启动当前连接的读数据业务 go c.StartReader() for { select { case <-c.ExitBuffChan: // 得到退出消息,不再阻塞 return } } } // Stop 停止连接,结束当前连接状态 func (c *Connection) Stop() { if c.IsClosed { return } c.IsClosed = true // TODO 如果用户注册了该连接的关闭回调业务,那么在此刻应该显式调用 // 关闭 Socket 连接 _ = c.Conn.Close() // 通知从缓冲队列读取数据的业务,该连接已经关闭 c.ExitBuffChan <- struct{}{} // 关闭该连接的全部管道 close(c.ExitBuffChan) } // GetTCPConnection 获取当前连接的 TCP Socket 套接字 func (c *Connection) GetTCPConnection() *net.TCPConn { return c.Conn } // GetConnID 获取当前连接 ID func (c *Connection) GetConnID() uint32 { return c.ConnID } // RemoteAddr 获取远程客户端地址信息 func (c *Connection) RemoteAddr() net.Addr { return c.Conn.RemoteAddr() }