Exemple #1
0
        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;
                }
            }
        }
Exemple #2
0
        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;
                }
            }
        }
Exemple #3
0
        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;
                }
            }
        }