- 7.1 Zinx-V0.7代码实现
- A) 添加读写模块交互数据的管道
- B) 创建Writer Goroutine
- C) Reader讲发送客户端的数据改为发送至Channel
7.1 Zinx-V0.7代码实现
我们的代码改动并不是很大。
A) 添加读写模块交互数据的管道
zinx/znet/connection.go
type Connection struct {//当前连接的socket TCP套接字Conn *net.TCPConn//当前连接的ID 也可以称作为SessionID,ID全局唯一ConnID uint32//当前连接的关闭状态isClosed bool//消息管理MsgId和对应处理方法的消息管理模块MsgHandler ziface.IMsgHandle//告知该链接已经退出/停止的channelExitBuffChan chan bool//无缓冲管道,用于读、写两个goroutine之间的消息通信msgChan chan []byte}//创建连接的方法func NewConntion(conn *net.TCPConn, connID uint32, msgHandler ziface.IMsgHandle) *Connection{c := &Connection{Conn: conn,ConnID: connID,isClosed: false,MsgHandler: msgHandler,ExitBuffChan: make(chan bool, 1),msgChan:make(chan []byte), //msgChan初始化}return c}
我们给Connection新增一个管道成员msgChan,作用是用于读写两个go的通信。
B) 创建Writer Goroutine
zinx/znet/connection.go
/*写消息Goroutine, 用户将数据发送给客户端*/func (c *Connection) StartWriter() {fmt.Println("[Writer Goroutine is running]")defer fmt.Println(c.RemoteAddr().String(), "[conn Writer exit!]")for {select {case data := <-c.msgChan://有数据要写给客户端if _, err := c.Conn.Write(data); err != nil {fmt.Println("Send Data error:, ", err, " Conn Writer exit")return}case <- c.ExitBuffChan://conn已经关闭return}}}
C) Reader讲发送客户端的数据改为发送至Channel
修改Reader调用的SendMsg()方法
zinx/znet/connection.go
//直接将Message数据发送数据给远程的TCP客户端func (c *Connection) SendMsg(msgId uint32, data []byte) error {if c.isClosed == true {return errors.New("Connection closed when send msg")}//将data封包,并且发送dp := NewDataPack()msg, err := dp.Pack(NewMsgPackage(msgId, data))if err != nil {fmt.Println("Pack error msg id = ", msgId)return errors.New("Pack error msg ")}//写回客户端c.msgChan <- msg //将之前直接回写给conn.Write的方法 改为 发送给Channel 供Writer读取return nil}
D) 启动Reader和Writer
zinx/znet/connection.go
//启动连接,让当前连接开始工作func (c *Connection) Start() {//1 开启用户从客户端读取数据流程的Goroutinego c.StartReader()//2 开启用于写回客户端数据流程的Goroutinego c.StartWriter()for {select {case <- c.ExitBuffChan://得到退出消息,不再阻塞return}}}
