|
|
@ -10,6 +10,8 @@ import ( |
|
|
|
) |
|
|
|
|
|
|
|
type Connection struct { |
|
|
|
//当前Conn属于哪个Server
|
|
|
|
TcpServer ziface.IServer |
|
|
|
//当前连接的socket TCP套接字
|
|
|
|
Conn *net.TCPConn |
|
|
|
//当前连接的ID 也可以称作为SessionID,ID全局唯一
|
|
|
@ -22,21 +24,27 @@ type Connection struct { |
|
|
|
ExitBuffChan chan bool |
|
|
|
//无缓冲管道,用于读、写两个goroutine之间的消息通信
|
|
|
|
msgChan chan []byte |
|
|
|
//有关冲管道,用于读、写两个goroutine之间的消息通信
|
|
|
|
msgBuffChan chan []byte |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//创建连接的方法
|
|
|
|
func NewConntion(conn *net.TCPConn, connID uint32, msgHandler ziface.IMsgHandle) *Connection{ |
|
|
|
func NewConntion(server ziface.IServer, conn *net.TCPConn, connID uint32, msgHandler ziface.IMsgHandle) *Connection{ |
|
|
|
//初始化Conn属性
|
|
|
|
c := &Connection{ |
|
|
|
TcpServer:server, |
|
|
|
Conn: conn, |
|
|
|
ConnID: connID, |
|
|
|
isClosed: false, |
|
|
|
MsgHandler: msgHandler, |
|
|
|
ExitBuffChan: make(chan bool, 1), |
|
|
|
msgChan:make(chan []byte), |
|
|
|
// SendBuffChan: make(chan []byte, 512),
|
|
|
|
msgBuffChan:make(chan []byte, utils.GlobalObject.MaxMsgChanLen), |
|
|
|
} |
|
|
|
|
|
|
|
//将新创建的Conn添加到链接管理中
|
|
|
|
c.TcpServer.GetConnMgr().Add(c) |
|
|
|
return c |
|
|
|
} |
|
|
|
|
|
|
@ -44,9 +52,8 @@ func NewConntion(conn *net.TCPConn, connID uint32, msgHandler ziface.IMsgHandle) |
|
|
|
写消息Goroutine, 用户将数据发送给客户端 |
|
|
|
*/ |
|
|
|
func (c *Connection) StartWriter() { |
|
|
|
|
|
|
|
defer fmt.Println(c.RemoteAddr().String(), " conn Writer exit!") |
|
|
|
defer c.Stop() |
|
|
|
fmt.Println("[Writer Goroutine is running]") |
|
|
|
defer fmt.Println(c.RemoteAddr().String(), "[conn Writer exit!]") |
|
|
|
|
|
|
|
for { |
|
|
|
select { |
|
|
@ -56,6 +63,16 @@ func NewConntion(conn *net.TCPConn, connID uint32, msgHandler ziface.IMsgHandle) |
|
|
|
fmt.Println("Send Data error:, ", err, " Conn Writer exit") |
|
|
|
return |
|
|
|
} |
|
|
|
case data, ok:= <-c.msgBuffChan: |
|
|
|
if ok { |
|
|
|
//有数据要写给客户端
|
|
|
|
if _, err := c.Conn.Write(data); err != nil { |
|
|
|
fmt.Println("Send Buff Data error:, ", err, " Conn Writer exit") |
|
|
|
return |
|
|
|
} |
|
|
|
} else { |
|
|
|
fmt.Println("msgBuffChan is Closed") |
|
|
|
} |
|
|
|
case <- c.ExitBuffChan: |
|
|
|
//conn已经关闭
|
|
|
|
return |
|
|
@ -68,9 +85,8 @@ func NewConntion(conn *net.TCPConn, connID uint32, msgHandler ziface.IMsgHandle) |
|
|
|
读消息Goroutine,用于从客户端中读取数据 |
|
|
|
*/ |
|
|
|
func (c *Connection) StartReader() { |
|
|
|
fmt.Println("Reader Goroutine is running") |
|
|
|
defer fmt.Println(c.RemoteAddr().String(), " conn reader exit!") |
|
|
|
defer c.Stop() |
|
|
|
fmt.Println("[Reader Goroutine is running]") |
|
|
|
defer fmt.Println(c.RemoteAddr().String(), "[conn Reader exit!]") |
|
|
|
|
|
|
|
for { |
|
|
|
// 创建拆包解包的对象
|
|
|
@ -80,16 +96,14 @@ func (c *Connection) StartReader() { |
|
|
|
headData := make([]byte, dp.GetHeadLen()) |
|
|
|
if _, err := io.ReadFull(c.GetTCPConnection(), headData); err != nil { |
|
|
|
fmt.Println("read msg head error ", err) |
|
|
|
c.ExitBuffChan <- true |
|
|
|
continue |
|
|
|
break |
|
|
|
} |
|
|
|
|
|
|
|
//拆包,得到msgid 和 datalen 放在msg中
|
|
|
|
msg , err := dp.Unpack(headData) |
|
|
|
if err != nil { |
|
|
|
fmt.Println("unpack error ", err) |
|
|
|
c.ExitBuffChan <- true |
|
|
|
continue |
|
|
|
break |
|
|
|
} |
|
|
|
|
|
|
|
//根据 dataLen 读取 data,放在msg.Data中
|
|
|
@ -98,8 +112,7 @@ func (c *Connection) StartReader() { |
|
|
|
data = make([]byte, msg.GetDataLen()) |
|
|
|
if _, err := io.ReadFull(c.GetTCPConnection(), data); err != nil { |
|
|
|
fmt.Println("read msg data error ", err) |
|
|
|
c.ExitBuffChan <- true |
|
|
|
continue |
|
|
|
break |
|
|
|
} |
|
|
|
} |
|
|
|
msg.SetData(data) |
|
|
@ -118,20 +131,28 @@ func (c *Connection) StartReader() { |
|
|
|
go c.MsgHandler.DoMsgHandler(&req) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
c.ExitBuffChan <- true |
|
|
|
} |
|
|
|
|
|
|
|
//启动连接,让当前连接开始工作
|
|
|
|
func (c *Connection) Start() { |
|
|
|
//Start()函数结束的时候就应该调用Stop处理善后业务
|
|
|
|
defer c.Stop() |
|
|
|
|
|
|
|
//1 开启用户从客户端读取数据流程的Goroutine
|
|
|
|
go c.StartReader() |
|
|
|
//2 开启用于写回客户端数据流程的Goroutine
|
|
|
|
go c.StartWriter() |
|
|
|
|
|
|
|
//按照用户传递进来的创建连接时需要处理的业务,执行钩子方法
|
|
|
|
c.TcpServer.CallOnConnStart(c) |
|
|
|
|
|
|
|
for { |
|
|
|
select { |
|
|
|
case <- c.ExitBuffChan: |
|
|
|
//得到退出消息,不再阻塞
|
|
|
|
fmt.Println("Start recv ExitBuffChan...") |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
@ -139,23 +160,25 @@ func (c *Connection) Start() { |
|
|
|
|
|
|
|
//停止连接,结束当前连接状态M
|
|
|
|
func (c *Connection) Stop() { |
|
|
|
fmt.Println("Conn Stop()...ConnID = ", c.ConnID) |
|
|
|
//1. 如果当前链接已经关闭
|
|
|
|
if c.isClosed == true { |
|
|
|
return |
|
|
|
} |
|
|
|
c.isClosed = true |
|
|
|
|
|
|
|
//TODO Connection Stop() 如果用户注册了该链接的关闭回调业务,那么在此刻应该显示调用
|
|
|
|
//如果用户注册了该链接的关闭回调业务,那么在此刻应该显示调用
|
|
|
|
c.TcpServer.CallOnConnStop(c) |
|
|
|
|
|
|
|
// 关闭socket链接
|
|
|
|
c.Conn.Close() |
|
|
|
|
|
|
|
//通知从缓冲队列读数据的业务,该链接已经关闭
|
|
|
|
c.ExitBuffChan <- true |
|
|
|
//将链接从连接管理器中删除
|
|
|
|
c.TcpServer.GetConnMgr().Remove(c) |
|
|
|
|
|
|
|
//关闭该链接全部管道
|
|
|
|
close(c.ExitBuffChan) |
|
|
|
//close(c.SendBuffChan)
|
|
|
|
close(c.msgBuffChan) |
|
|
|
} |
|
|
|
|
|
|
|
//从当前连接获取原始的socket TCPConn
|
|
|
@ -190,4 +213,22 @@ func (c *Connection) SendMsg(msgId uint32, data []byte) error { |
|
|
|
c.msgChan <- msg |
|
|
|
|
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Connection) SendBuffMsg(msgId uint32, data []byte) error { |
|
|
|
if c.isClosed == true { |
|
|
|
return errors.New("Connection closed when send buff 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.msgBuffChan <- msg |
|
|
|
|
|
|
|
return nil |
|
|
|
} |