//发送循环 func (r *Robot) SendLoop() { defer r.Close() elog.LogDebug(" robot %d send loop run ", r.id) for { select { case msg := <-r.sendCh: //从发送通道取出待发送消息 elog.LogInfo(" encode msg :%d ", msg.id) binary.Write(r.sendBuf, binary.LittleEndian, msg.id) //写ID binary.Write(r.sendBuf, binary.LittleEndian, msg.Data) //写数据 byte := r.sendBuf.Bytes() n, err := r.tcpConn.Write(byte) if err != nil { elog.LogSysln(" conn ", r.id, " write data fail :", err) return } elog.LogInfo(" write msg :%d ", n, hex.Dump(r.sendBuf.Bytes())) case <-r.closeCh: //机器人关闭信号 elog.LogDebug(" send loop begin close ") return } } elog.LogDebug("send loop close ") }
//执行一个回调函数 func (w *WaitGroupWrapper) Run(cb func()) { w.Add(1) elog.LogDebug("------ wait gropu add 1") go func() { cb() w.Done() elog.LogDebug(" wait gropu del 1") }() }
//接收循环 func (r *Robot) RecvLoop() { defer r.Close() elog.LogDebug(" robot %d read loop run ", r.id) buf := make([]byte, 1024*1024) for { select { case <-r.closeCh: //机器人关闭信号 elog.LogSysln("read loop begin stop ") return default: } r.tcpConn.SetDeadline(time.Now().Add(1e9)) n, err := r.tcpConn.Read(buf) if err != nil { if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() { continue } elog.LogErrorln(" read data error ", err) return } elog.LogSys(" ********* read data : %d ", n) r.recvBuf.Write(buf[0:n]) var msg Message binary.Read(r.recvBuf, binary.LittleEndian, msg.id) msg.Data = make([]byte, r.recvBuf.Len()) r.recvBuf.Read(msg.Data) r.recvCh <- msg } }
//创建机器人 func (rbMng *RobotMng) NewRobot() { r := NewRobot(rbMng.delCh, rbMng.closeCh, rbMng.waitGroup) //创建机器人 r.id = atomic.AddUint32(&rbMng.lastRobotId, 1) //计算机器人ID rbMng.AddRobot(r) //添加机器人 elog.LogDebug(" create robot %d ", r.id) r.SetUpdateCb(rbMng.upCb) //设置更新回调 rbMng.waitGroup.Run(r.Run) //启动机器人 }
//关闭机器人管理器 func (rbMng *RobotMng) Close() { elog.LogDebug(" .......................begin close ........................") rbMng.ticker.Stop() //先关闭机器人管理器时钟,这样就不会检测缺少的机器人 elog.LogDebug(" rbMng ticket stop") for _, r := range rbMng.robots { //关闭所有机器人 r.Close() //内部会告诉机器人管理器删除机器人 } close(rbMng.closeCh) //关闭通道,机器人管理器心跳结束 elog.LogDebug(" rbmng closech already close ") rbMng.waitGroup.Wait() //等待所有机器人关闭 elog.LogDebug(" rbMng wait all robot close ") //最后关del ch close(rbMng.delCh) //关闭删除通道 elog.LogDebug(" rbMng delCh close ") elog.LogDebug(" Everything is ok, i quit ....................................") }
//启动机器人 func (r *Robot) Run() { elog.LogDebug(" robot %d begin run ", r.id) var err error r.addr, err = net.ResolveTCPAddr("tcp", gateAddr) //解析服务器地址 if err != nil { elog.LogErrorln(gateAddr, ":resolve tcp addr fail, please try: 127.0.0.1:3563, fail: ", err) return } r.tcpConn, err = net.DialTCP("tcp", nil, r.addr) //连接服务器 if err != nil { elog.LogErrorln("connect server fail , because :", err) return } elog.LogInfoln(" connect server sucess :", r.id, r.tcpConn.RemoteAddr().String()) r.state = kRobotActive //设置机器人状态 r.waitGroup.Run(r.SendLoop) //启动发送循环 r.waitGroup.Run(r.RecvLoop) //启动接收循环 r.ticker = time.NewTicker(defDur) //启动机器人时钟 defer r.Close() //延迟关闭机器人 for { select { case <-r.closeCh: //关闭通道 elog.LogDebugln("update loop begin stop ") return case <-r.ticker.C: //时钟到时 //逻辑处理 r.update() //elog.LogInfoln("robot :", r.id, "heart :", t) default: } } }