You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

192 lines
4.3 KiB

  1. package znet
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. "net"
  7. "zinx/utils"
  8. "zinx/ziface"
  9. )
  10. type Connection struct {
  11. //当前连接的socket TCP套接字
  12. Conn *net.TCPConn
  13. //当前连接的ID 也可以称作为SessionID,ID全局唯一
  14. ConnID uint32
  15. //当前连接的关闭状态
  16. isClosed bool
  17. //消息管理MsgId和对应处理方法的消息管理模块
  18. MsgHandler ziface.IMsgHandle
  19. //告知该链接已经退出/停止的channel
  20. ExitBuffChan chan bool
  21. //无缓冲管道,用于读、写两个goroutine之间的消息通信
  22. msgChan chan []byte
  23. }
  24. //创建连接的方法
  25. func NewConntion(conn *net.TCPConn, connID uint32, msgHandler ziface.IMsgHandle) *Connection{
  26. c := &Connection{
  27. Conn: conn,
  28. ConnID: connID,
  29. isClosed: false,
  30. MsgHandler: msgHandler,
  31. ExitBuffChan: make(chan bool, 1),
  32. msgChan:make(chan []byte),
  33. // SendBuffChan: make(chan []byte, 512),
  34. }
  35. return c
  36. }
  37. /*
  38. 写消息Goroutine 用户将数据发送给客户端
  39. */
  40. func (c *Connection) StartWriter() {
  41. defer fmt.Println(c.RemoteAddr().String(), " conn Writer exit!")
  42. defer c.Stop()
  43. for {
  44. select {
  45. case data := <-c.msgChan:
  46. //有数据要写给客户端
  47. if _, err := c.Conn.Write(data); err != nil {
  48. fmt.Println("Send Data error:, ", err, " Conn Writer exit")
  49. return
  50. }
  51. case <- c.ExitBuffChan:
  52. //conn已经关闭
  53. return
  54. }
  55. }
  56. }
  57. /*
  58. 读消息Goroutine用于从客户端中读取数据
  59. */
  60. func (c *Connection) StartReader() {
  61. fmt.Println("Reader Goroutine is running")
  62. defer fmt.Println(c.RemoteAddr().String(), " conn reader exit!")
  63. defer c.Stop()
  64. for {
  65. // 创建拆包解包的对象
  66. dp := NewDataPack()
  67. //读取客户端的Msg head
  68. headData := make([]byte, dp.GetHeadLen())
  69. if _, err := io.ReadFull(c.GetTCPConnection(), headData); err != nil {
  70. fmt.Println("read msg head error ", err)
  71. c.ExitBuffChan <- true
  72. continue
  73. }
  74. //拆包,得到msgid 和 datalen 放在msg中
  75. msg , err := dp.Unpack(headData)
  76. if err != nil {
  77. fmt.Println("unpack error ", err)
  78. c.ExitBuffChan <- true
  79. continue
  80. }
  81. //根据 dataLen 读取 data,放在msg.Data中
  82. var data []byte
  83. if msg.GetDataLen() > 0 {
  84. data = make([]byte, msg.GetDataLen())
  85. if _, err := io.ReadFull(c.GetTCPConnection(), data); err != nil {
  86. fmt.Println("read msg data error ", err)
  87. c.ExitBuffChan <- true
  88. continue
  89. }
  90. }
  91. msg.SetData(data)
  92. //得到当前客户端请求的Request数据
  93. req := Request{
  94. conn:c,
  95. msg:msg,
  96. }
  97. if utils.GlobalObject.WorkerPoolSize > 0 {
  98. //已经启动工作池机制,将消息交给Worker处理
  99. c.MsgHandler.SendMsgToTaskQueue(&req)
  100. } else {
  101. //从绑定好的消息和对应的处理方法中执行对应的Handle方法
  102. go c.MsgHandler.DoMsgHandler(&req)
  103. }
  104. }
  105. }
  106. //启动连接,让当前连接开始工作
  107. func (c *Connection) Start() {
  108. //1 开启用户从客户端读取数据流程的Goroutine
  109. go c.StartReader()
  110. //2 开启用于写回客户端数据流程的Goroutine
  111. go c.StartWriter()
  112. for {
  113. select {
  114. case <- c.ExitBuffChan:
  115. //得到退出消息,不再阻塞
  116. return
  117. }
  118. }
  119. }
  120. //停止连接,结束当前连接状态M
  121. func (c *Connection) Stop() {
  122. //1. 如果当前链接已经关闭
  123. if c.isClosed == true {
  124. return
  125. }
  126. c.isClosed = true
  127. //TODO Connection Stop() 如果用户注册了该链接的关闭回调业务,那么在此刻应该显示调用
  128. // 关闭socket链接
  129. c.Conn.Close()
  130. //通知从缓冲队列读数据的业务,该链接已经关闭
  131. c.ExitBuffChan <- true
  132. //关闭该链接全部管道
  133. close(c.ExitBuffChan)
  134. //close(c.SendBuffChan)
  135. }
  136. //从当前连接获取原始的socket TCPConn
  137. func (c *Connection) GetTCPConnection() *net.TCPConn {
  138. return c.Conn
  139. }
  140. //获取当前连接ID
  141. func (c *Connection) GetConnID() uint32{
  142. return c.ConnID
  143. }
  144. //获取远程客户端地址信息
  145. func (c *Connection) RemoteAddr() net.Addr {
  146. return c.Conn.RemoteAddr()
  147. }
  148. //直接将Message数据发送数据给远程的TCP客户端
  149. func (c *Connection) SendMsg(msgId uint32, data []byte) error {
  150. if c.isClosed == true {
  151. return errors.New("Connection closed when send msg")
  152. }
  153. //将data封包,并且发送
  154. dp := NewDataPack()
  155. msg, err := dp.Pack(NewMsgPackage(msgId, data))
  156. if err != nil {
  157. fmt.Println("Pack error msg id = ", msgId)
  158. return errors.New("Pack error msg ")
  159. }
  160. //写回客户端
  161. c.msgChan <- msg
  162. return nil
  163. }