コード例 #1
0
 private void Serialize(MemoryStream ms, ProtoMessage msg)
 {
     if (msg.Data != null)
     {
         Serializer.Serialize <IExtensible> (ms, msg.Data);
     }
 }
コード例 #2
0
 public void Enqueue(ProtoMessage msg)
 {
     lock (this)
     {
         q.Enqueue(msg);
         Monitor.Pulse(this);
     }
 }
コード例 #3
0
        // Update method is called by outside MonoBehaviour object's Update method
        public void Update()
        {
            // 定期检查心跳,分发消息处理,由外部的MonoBehaviour对象驱动
            if (_running)
            {
                if (_needHB)
                {
                    long nowms = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

                    if (nowms - _lastRecvHBTime > Constants.CORPC_MAX_NO_HEARTBEAT_TIME)
                    {
                        // 无心跳,断线
                        Debug.LogError("heartbeat timeout");
                        Close();
                    }
                    else if (nowms - _lastSendHBTime > Constants.CORPC_HEARTBEAT_PERIOD)
                    {
                        Send(Constants.CORPC_MSG_TYPE_HEARTBEAT, null);
                        _lastSendHBTime = nowms;
                    }
                }

                // 心跳和断线消息需要特殊处理
                ProtoMessage pmsg = _recvMsgQueue.Dequeue();
                while (pmsg != null)
                {
                    switch (pmsg.Type)
                    {
                    case Constants.CORPC_MSG_TYPE_DISCONNECT:
                    {
                        Close();

                        // 清理收发队列(主要是发送队列)
                        // 注意:此时收发线程已经退出,对收发队列的处理没有线程同步的问题
                        _recvMsgQueue.Clear();
                        _sendMsgQueue.Clear();

                        Dispatch(Constants.CORPC_MSG_TYPE_DISCONNECT, null);
                        break;
                    }

                    case Constants.CORPC_MSG_TYPE_HEARTBEAT:
                    {
                        _lastRecvHBTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
                        break;
                    }

                    default:
                    {
                        Dispatch(pmsg.Type, pmsg.Data);
                        break;
                    }
                    }

                    pmsg = _recvMsgQueue.Dequeue();
                }
            }
        }
コード例 #4
0
        protected byte[] Serialize(ProtoMessage msg)
        {
            if (msg.Data != null)
            {
                return(msg.Data.ToByteArray());
            }

            Debug.LogErrorFormat("Serialize empty msg [{0}]!!!", msg.Type);
            return(null);
        }
コード例 #5
0
        private void SendMsgLoop()
        {
            while (true)
            {
                ProtoMessage msg = null;
                try {
                    msg = _sendMsgQueue.Dequeue();

                    Debug.Assert(msg != null);

                    if (msg.Type == Constants.CORPC_MSG_TYPE_DISCONNECT)
                    {
                        return;
                    }
                    else
                    {
                        // 构造要发出的消息数据
                        MemoryStream ms = new MemoryStream();
                        Serialize(ms, msg);

                        int    dataLength = (int)ms.Length;
                        byte[] buf        = new byte[8 + 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 >> 24) & 0xFF);
                        buf[5] = (byte)((msg.Type >> 16) & 0xFF);
                        buf[6] = (byte)((msg.Type >> 8) & 0xFF);
                        buf[7] = (byte)(msg.Type & 0xFF);

                        ms.Position = 0;
                        int remainLen = dataLength;
                        while (remainLen > 0)
                        {
                            remainLen -= ms.Read(buf, 8 + dataLength - remainLen, remainLen);
                        }

                        _udpSocket.Send(buf);
                    }
                } catch (System.Exception ex) {
                    Debug.LogError("SendMsgLoop error!!! --- ");
                    Debug.LogError(ex.ToString());
                    Debug.LogError(ex.StackTrace);
                    return;
                }
            }
        }
コード例 #6
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;
                }
            }
        }
コード例 #7
0
        // Update method is called by outside MonoBehaviour object's Update method
        public void Update()
        {
            // 定期检查心跳,分发消息处理,由外部的MonoBehaviour对象驱动
            if (_running)
            {
                long nowms = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

                if (nowms - _lastRecvHBTime > Constants.CORPC_MAX_NO_HEARTBEAT_TIME)
                {
                    // 无心跳,断线
                    Debug.LogError("heartbeat timeout");
                    Close();
                }
                else if (nowms - _lastSendHBTime > Constants.CORPC_HEARTBEAT_PERIOD)
                {
                    if (_shakeOK)
                    {
                        Send(Constants.CORPC_MSG_TYPE_HEARTBEAT, 0, null, false);
                        _lastSendHBTime = nowms;
                    }
                }

                // 心跳和断线消息需要特殊处理
                ProtoMessage pmsg = _recvMsgQueue.Dequeue();
                while (pmsg != null)
                {
                    switch (pmsg.Type)
                    {
                    case Constants.CORPC_MSG_TYPE_DISCONNECT:
                    case Constants.CORPC_MSG_TYPE_UDP_UNSHAKE:
                    {
                        Close();
                        break;
                    }

                    case Constants.CORPC_MSG_TYPE_UDP_HANDSHAKE_2:
                    {
                        if (!_shakeOK)
                        {
                            // 重发handshake_3
                            try {
                                _udpSocket.Send(_handshake3msg);
                            }  catch (System.Exception ex) {
                                Debug.LogError("Send handshake3 failed");
                                Debug.LogError(ex.ToString());
                                Debug.LogError(ex.StackTrace);
                                Close();
                                break;
                            }
                        }
                        break;
                    }

                    case Constants.CORPC_MSG_TYPE_UDP_HANDSHAKE_4:
                    {
                        _shakeOK = true;
                        Debug.Log("shake succeed");

                        // 启动发送线程
                        _sendMsgThread = new Thread(new ThreadStart(SendMsgLoop));
                        _sendMsgThread.Start();

                        break;
                    }

                    case Constants.CORPC_MSG_TYPE_HEARTBEAT:
                    {
                        _lastRecvHBTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
                        break;
                    }

                    default:
                    {
                        if (!_shakeOK)
                        {
                            Debug.LogError("recv msg when unshaked");
                            Close();
                            break;
                        }

                        HandleMessage(pmsg.Type, pmsg.Data);
                        break;
                    }
                    }

                    pmsg = _recvMsgQueue.Dequeue();
                }
            }
        }
コード例 #8
0
 public void Enqueue(ProtoMessage msg)
 {
     lock (this) {
         q.Enqueue(msg);
     }
 }