private void RecvMsgLoop() { byte[] buf = new byte[Constants.CORPC_MAX_UDP_MESSAGE_SIZE]; while (true) { try { int i = _udpSocket.Receive(buf); Debug.Assert(i >= Constants.CORPC_MESSAGE_HEAD_SIZE); int msgLen = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]; short msgType = (short)((buf[4] << 8) + buf[5]); ushort tag = (ushort)((buf[6] << 8) + buf[7]); ushort flag = (ushort)((buf[8] << 8) + buf[9]); Debug.Assert(i == Constants.CORPC_MESSAGE_HEAD_SIZE + msgLen); IMessage protoData = null; if (msgType > 0) { // 校验序号 if (_enableSerial) { uint serial = (uint)((buf[14] << 24) + (buf[15] << 16) + (buf[16] << 8) + buf[17]); if (serial != 0 && serial != _lastRecvSerial + 1) { Debug.LogErrorFormat("serial check failed! need %d, recv %d", _lastRecvSerial, serial); _recvMsgQueue.Enqueue(new ProtoMessage(Constants.CORPC_MSG_TYPE_DISCONNECT, 0, null, false)); return; } _lastRecvSerial++; } if (msgLen > 0) { // 校验CRC if (_enableRecvCRC) { ushort crc = (ushort)((buf[18] << 8) + buf[19]); ushort crc1 = CRC.CheckSum(buf, Constants.CORPC_MESSAGE_HEAD_SIZE, 0xFFFF, (uint)msgLen); if (crc != crc1) { Debug.LogErrorFormat("crc check failed, msgType:%d, size:%d, recv:%d, cal:%d\n", msgType, msgLen, crc, crc1); _recvMsgQueue.Enqueue(new ProtoMessage(Constants.CORPC_MSG_TYPE_DISCONNECT, 0, null, false)); return; } } // 解密 if ((flag & Constants.CORPC_MESSAGE_FLAG_CRYPT) != 0) { if (_crypter == null) { Debug.LogError("cant decrypt message for crypter not exist\n"); _recvMsgQueue.Enqueue(new ProtoMessage(Constants.CORPC_MSG_TYPE_DISCONNECT, 0, null, false)); return; } _crypter.decrypt(buf, Constants.CORPC_MESSAGE_HEAD_SIZE, buf, Constants.CORPC_MESSAGE_HEAD_SIZE, (uint)msgLen); } protoData = Deserialize(msgType, buf, Constants.CORPC_MESSAGE_HEAD_SIZE, msgLen); } } _recvMsgQueue.Enqueue(new ProtoMessage(msgType, tag, protoData, false)); } catch (System.Exception ex) { Debug.LogError("RecvThread error!!!"); Debug.LogError(ex.ToString()); Debug.LogError(ex.StackTrace); _recvMsgQueue.Enqueue(new ProtoMessage(Constants.CORPC_MSG_TYPE_DISCONNECT, 0, null, false)); return; } } }
private void SendMsgLoop() { byte[] buf = new byte[Constants.CORPC_MAX_UDP_MESSAGE_SIZE]; while (true) { ProtoMessage msg = null; try { msg = _sendMsgQueue.Dequeue(); Debug.Assert(msg != null); switch (msg.Type) { case Constants.CORPC_MSG_TYPE_DISCONNECT: { return; } case Constants.CORPC_MSG_TYPE_HEARTBEAT: { _udpSocket.Send(_heartbeatmsg, (int)Constants.CORPC_MESSAGE_HEAD_SIZE, SocketFlags.None); break; } default: { // 构造要发出的消息数据 byte[] data = Serialize(msg); uint dataLength = (uint)data.Length; if (Constants.CORPC_MESSAGE_HEAD_SIZE + dataLength > Constants.CORPC_MAX_UDP_MESSAGE_SIZE) { Debug.LogError("send message size too large!!!"); _recvMsgQueue.Enqueue(new ProtoMessage(Constants.CORPC_MSG_TYPE_DISCONNECT, 0, null, false)); return; } ushort flag = 0; if (dataLength > 0) { // 加密 if (msg.NeedCrypter) { _crypter.encrypt(data, 0, buf, Constants.CORPC_MESSAGE_HEAD_SIZE, dataLength); flag |= Constants.CORPC_MESSAGE_FLAG_CRYPT; } else { Array.Copy(data, 0, buf, Constants.CORPC_MESSAGE_HEAD_SIZE, dataLength); } } // 设置头部 buf[0] = (byte)((dataLength >> 24) & 0xFF); buf[1] = (byte)((dataLength >> 16) & 0xFF); buf[2] = (byte)((dataLength >> 8) & 0xFF); buf[3] = (byte)(dataLength & 0xFF); buf[4] = (byte)((msg.Type >> 8) & 0xFF); buf[5] = (byte)(msg.Type & 0xFF); buf[6] = (byte)((msg.Tag >> 8) & 0xFF); buf[7] = (byte)(msg.Tag & 0xFF); buf[8] = (byte)((flag >> 8) & 0xFF); buf[9] = (byte)(flag & 0xFF); if (_enableSerial) { // _lastRecvSerial是否会导致线程同步问题? buf[10] = (byte)((_lastRecvSerial >> 24) & 0xFF); buf[11] = (byte)((_lastRecvSerial >> 16) & 0xFF); buf[12] = (byte)((_lastRecvSerial >> 8) & 0xFF); buf[13] = (byte)(_lastRecvSerial & 0xFF); _lastSendSerial++; buf[14] = (byte)((_lastSendSerial >> 24) & 0xFF); buf[15] = (byte)((_lastSendSerial >> 16) & 0xFF); buf[16] = (byte)((_lastSendSerial >> 8) & 0xFF); buf[17] = (byte)(_lastSendSerial & 0xFF); } if (_enableSendCRC) { ushort crc = CRC.CheckSum(buf, 0, 0xFFFF, Constants.CORPC_MESSAGE_HEAD_SIZE - 2); crc = CRC.CheckSum(buf, Constants.CORPC_MESSAGE_HEAD_SIZE, crc, dataLength); buf[18] = (byte)((crc >> 8) & 0xFF); buf[19] = (byte)(crc & 0xFF); } _udpSocket.Send(buf, (int)(Constants.CORPC_MESSAGE_HEAD_SIZE + dataLength), SocketFlags.None); break; } } } catch (System.Exception ex) { Debug.LogError("SendMsgLoop error!!! --- "); Debug.LogError(ex.ToString()); Debug.LogError(ex.StackTrace); return; } } }
private void RecvMsgLoop() { byte[] head = new byte[Constants.CORPC_MESSAGE_HEAD_SIZE]; while (true) { try { // 读出消息头部(4字节类型+4字节长度) // |body size(4 bytes)|message type(2 bytes)|tag(2 byte)|flag(2 byte)|req serial number(4 bytes)|serial number(4 bytes)|crc(2 bytes)| int remainLen = Constants.CORPC_MESSAGE_HEAD_SIZE; while (remainLen > 0) { remainLen -= _stream.Read(head, Constants.CORPC_MESSAGE_HEAD_SIZE - remainLen, remainLen); } uint msgLen = (uint)((head[0] << 24) + (head[1] << 16) + (head[2] << 8) + head[3]); short msgType = (short)((head[4] << 8) + head[5]); ushort tag = (ushort)((head[6] << 8) + head[7]); ushort flag = (ushort)((head[8] << 8) + head[9]); // 读取消息体 byte[] data = null; if (msgLen > 0) { // TODO: 校验服务器发给客户端消息大小,超过阈值报警 // 注意:目前每个消息分配内存的实现会产生较多的回收垃圾,可以改为分配一个最大空间重复使用 data = new byte[msgLen]; remainLen = (int)msgLen; while (remainLen > 0) { remainLen -= _stream.Read(data, (int)msgLen - remainLen, remainLen); //Console.WriteLine("remainLen = " + remainLen + " : " + (DateTime.Now.Ticks/TimeSpan.TicksPerMillisecond-startTimeStamp)); } } IMessage protoData = null; if (msgType > 0) { // 校验序号 if (_enableSerial) { uint serial = (uint)((head[14] << 24) + (head[15] << 16) + (head[16] << 8) + head[17]); if (serial != 0 && serial != _lastRecvSerial + 1) { Debug.LogErrorFormat("serial check failed! need {0}, recv {1}", _lastRecvSerial, serial); _recvMsgQueue.Enqueue(new ProtoMessage(Constants.CORPC_MSG_TYPE_DISCONNECT, 0, null, false)); return; } _lastRecvSerial++; } if (msgLen > 0) { // 校验CRC if (_enableRecvCRC) { ushort crc = (ushort)((head[18] << 8) + head[19]); ushort crc1 = CRC.CheckSum(data, 0, 0xFFFF, msgLen); if (crc != crc1) { Debug.LogErrorFormat("crc check failed, msgType:{0}, size:{1}, recv:{2}, cal:{3}\n", msgType, msgLen, crc, crc1); _recvMsgQueue.Enqueue(new ProtoMessage(Constants.CORPC_MSG_TYPE_DISCONNECT, 0, null, false)); return; } } // 解密 if ((flag & Constants.CORPC_MESSAGE_FLAG_CRYPT) != 0) { if (_crypter == null) { Debug.LogError("cant decrypt message for crypter not exist\n"); _recvMsgQueue.Enqueue(new ProtoMessage(Constants.CORPC_MSG_TYPE_DISCONNECT, 0, null, false)); return; } _crypter.decrypt(data, 0, data, 0, msgLen); } protoData = Deserialize(msgType, data, 0, (int)msgLen); } } _recvMsgQueue.Enqueue(new ProtoMessage(msgType, tag, protoData, false)); } catch (System.Exception ex) { Debug.LogError("RecvThread error!!!"); Debug.LogError(ex.ToString()); Debug.LogError(ex.StackTrace); _recvMsgQueue.Enqueue(new ProtoMessage(Constants.CORPC_MSG_TYPE_DISCONNECT, 0, null, false)); return; } } }