示例#1
0
        // 关闭连接
        public void OnClosed(object sender, EventArgs e)
        {
            try
            {
                mClient.Client.Shutdown(SocketShutdown.Both);
                mClient.GetStream().Close();
                mClient.Close();
                mClient = null;
            }
            catch (Exception exc)
            {
                DebugEx.Log(exc.ToString());
            }

            EnableConnect = false;
            mConnectState = EConnectState.None;
            mRecvResult   = null;
            mClient       = null;
            mRecvPos      = 0;
            mReceiveCount = 0;
            mConnectCount = 0;
            mMessageQueue.Clear();

            if (OnConnectClosed != null)
            {
                OnConnectClosed();
            }
        }
示例#2
0
        public void OnConnectError(object sender, ErrorEventArgs e)
        {
            mConnectState = EConnectState.None;
            DebugEx.Log("connect error, ready to close");

            try
            {
                mClient.Client.Shutdown(SocketShutdown.Both);
                mClient.GetStream().Close();
                mClient.Close();
                mClient = null;
            }
            catch (Exception exc)
            {
                DebugEx.Log(exc.ToString());
            }
            mRecvResult   = null;
            mClient       = null;
            mRecvPos      = 0;
            mReceiveCount = 0;
            mConnectCount = 0;

            if (OnConnectServerFailed != null)
            {
                OnConnectServerFailed();
            }
        }
示例#3
0
        public void Disconnect()
        {
            ConnectState = EConnectState.None;
            hostID       = HostID_None;

            lock (csSend)
            {
                queSend.Clear();
            }

            try
            {
                if (socket == null)
                {
                    Debug.Log("NetClient.Disconnect() : socket == null");
                    return;
                }

                Debug.Log("NetClient.Disconnect()");

                socket.Close();
            }
            catch (Exception ex)
            {
                Debug.Log("NetClient.Disconnect() exception : " + ex.ToString());

                socket.Close();
            }
        }
示例#4
0
 private void FinCountdown()
 {
     Log.Info("[Info] Connection Closed");
     _eConnectState = EConnectState.CLOSED;
     _socket.Disconnect(false);
     _socket.Close();
     _socket.Dispose();
 }
示例#5
0
        /*
         * Socket.BeginConnect() 에 바인딩 되어 접속 완료시 호출
         * P.S : host thread 에서 호출됨
         */
        private void OnCallbackConnect(IAsyncResult _iar)
        {
            try
            {
                Socket socketTemp = (Socket)_iar.AsyncState;

                if (socketTemp.Connected == false)
                {
                    if (ConnectState == EConnectState.None)
                    {
                        ErrorTypeJoinServerComplete = ErrorType.ErrorType_TCPConnectFailure;
                    }

                    Debug.Log("OnCallbackConnect() : 접속 실패.!");
                    return;
                }

                socketTemp.EndConnect(_iar);

                // 메세지 리시브 대기
                buffRecvSize = 0;
                socket.BeginReceive(bufferRecv, buffRecvSize, bufferRecv.Length, SocketFlags.None, asyncCallbackRecv, socket);

                ConnectState = EConnectState.ConnectVerify;

                Debug.Log("OnCallbackConnect().!");
            }
            catch (Exception ex)
            {
                Debug.Log("OnCallbackConnect() exception : " + ex.ToString());

                switch (ConnectState)
                {
                case EConnectState.ConnectBegin:
                {
                    ErrorTypeJoinServerComplete = ErrorType.ErrorType_TCPConnectFailure;
                    ConnectState = EConnectState.None;
                }
                break;

                case EConnectState.ReconnectBegin:
                {
                    ConnectState = EConnectState.ReconnectFail;
                }
                break;
                }

                if (socket != null)
                {
                    socket.Close();
                }
            }
        }
示例#6
0
    void SendFIN()
    {
        Log.Info("[Info] Send FIN");
        Message msg = new Message();

        msg.seq  = GetCliSeq();
        msg.ack  = GetSvrSeq();
        msg.syn  = 0;
        msg.fin  = 1;
        msg.rsd  = 0;
        msg.ctrl = (byte)ESAFlag.Ctrl;
        UInt16 len = msg.GetLength();

        msg.len = len;
        _ringSendMsgAckBuffer[msg.seq] = msg;
        _sender.Send(msg);
        _eConnectState = EConnectState.FIN_WAIT_1;
        //        _finishTick = Time.realtimeSinceStartup;
    }
示例#7
0
    private void SendSYN()
    {
        Log.Info("[Info] Send SYN");
        Message msg = new Message();

        msg.seq  = GetCliSeq();
        msg.ack  = GetSvrSeq();
        msg.syn  = 1;
        msg.fin  = 0;
        msg.rsd  = 1;
        msg.ctrl = (byte)ESAFlag.Ctrl;
        UInt16 len = msg.GetLength();

        msg.len = len;
        _ringSendMsgAckBuffer[msg.seq] = msg;
        _sender.SendImmediate(msg);
        _eConnectState = EConnectState.SYN_SENT;
        Log.InfoFormat("[Info] SendSYN seq = {0} ack = {1}", msg.seq, msg.ack);
    }
示例#8
0
    public void Connect(string ip, int port)
    {
        m_strServerIP = ip;
        m_nServerPort = port;
        object privateLockObject;

        Monitor.Enter(privateLockObject = m_PrivateLockObject);
        try
        {
            m_ConnectState = EConnectState.PostConnecting;
            //GameDll.CGameProcedure.s_EventManager.OnNetStateChanged.SafeInvoke((int)NetworkProtol.Tcp, (int)m_ConnectState);

            m_CurNetwork     = Application.internetReachability;
            m_uNextCheckTime = (uint)UnityEngine.Time.realtimeSinceStartup + 1000u;
        }
        finally
        {
            Monitor.Exit(privateLockObject);
        }
        Debug.Log(string.Concat(new object[] { "Connect:", ip, ":", port, " internettype:", m_CurNetwork }));
    }
示例#9
0
    private void SetState(EConnectState pState)
    {
        if (lastState == pState)
        {
            return;
        }

        //set delay so that state is not changed too quickly
        float delay = lastState == EConnectState.None ? 0 : lastChangeStateTime - Time.time + 1;

        delay = Mathf.Max(0, delay);

        lastState = pState;
        //Debug.Log($"Set state {pState} in {delay} | {Time.time}");
        DoInTime(() => UpdateUI(pState), delay);
        lastChangeStateTime = Time.time + delay;

        void UpdateUI(EConnectState pNewState)
        {
            switch (pNewState)
            {
            case EConnectState.Offline:
                background.color = Color.red;
                status.text      = "Offline";
                break;

            case EConnectState.Connecting:
                background.color = Color.magenta;
                status.text      = "Connecting...";
                break;

            case EConnectState.Online:
                background.color = Color.green;
                status.text      = "Online";
                break;
            }
        }
    }
示例#10
0
        // 异步连接远程主机
        public void Connect()
        {
            if (!EnableConnect)
            {
                return;
            }
            if (mCanConnectTime > Time.time)
            {
                return;
            }

            if (mClient != null)
            {
                throw new Exception("the socket is connecting, cannot connect again");
            }

            DebugEx.Log("satrt connect ip : " + mIP + " port : " + mPort);

            IPAddress ipAddress = IPAddress.Parse(mIP);

            try
            {
                mClient          = new TcpClient();
                mConnectResult   = mClient.BeginConnect(mIP, mPort, null, null);
                mConnectCount    = 0;
                mConnectOverTime = Time.time + mMaxConnectDuration;
                mConnectState    = EConnectState.Connecting;
            }
            catch (System.Exception exception)
            {
                DebugEx.LogError("connect exception : " + exception.ToString());
                mConnectResult = null;
                OnConnectError(mClient, null);
                throw;
            }
        }
示例#11
0
    private void ConnectServer()
    {
        object privateLockObject;

        Monitor.Enter(privateLockObject = m_PrivateLockObject);
        try
        {
            m_ConnectState = EConnectState.Connecting;
            //GameDll.CGameProcedure.s_EventManager.OnNetStateChanged.SafeInvoke((int)NetworkProtol.Tcp, (int)m_ConnectState);
        }
        finally
        {
            Monitor.Exit(privateLockObject);
        }
        if (m_Socket != null)
        {
            try
            {
                if (m_Socket.Connected)
                {
                    m_Socket.Shutdown(SocketShutdown.Both);
                    m_Socket.Disconnect(false);
                }
                m_Socket.Close();
            }
            catch (Exception exp)
            {
                Debug.LogError(exp.Message + exp.StackTrace);
            }
            m_Socket = null;
        }
        if (m_strServerIP != null && m_nServerPort != 0)
        {
            if (m_Socket == null)
            {
                m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            }
            m_Socket.Connect(m_strServerIP, m_nServerPort);
            m_Socket.Blocking = false;
        }
        Monitor.Enter(privateLockObject = m_PrivateLockObject);
        try
        {
            m_RecvQueue.Clear();
            m_SendQueue.Clear();
            if (m_ConnectState != EConnectState.PostConnecting)
            {
                if (m_Socket != null && m_Socket.Connected)
                {
                    m_ConnectState     = EConnectState.Connected;
                    m_bNetStateChanged = true;
                    //GameDll.CGameProcedure.s_EventManager.OnNetStateChanged.SafeInvoke((int)NetworkProtol.Tcp, (int)m_ConnectState);
                    Debug.Log("Connect Success");
                }
                else
                {
                    m_ConnectState     = EConnectState.Disconnected;
                    m_bNetStateChanged = true;
                    //GameDll.CGameProcedure.s_EventManager.OnNetStateChanged.SafeInvoke((int)NetworkProtol.Tcp, (int)m_ConnectState);
                }
            }
        }
        finally
        {
            Monitor.Exit(privateLockObject);
        }
    }
示例#12
0
    private void WfNetworkThread()
    {
        HeaderBytes headbytes = PooledClassManager <HeaderBytes> .CreateClass();

        DataBytes databytes  = null;
        int       recvedNum  = 0;
        WfPacket  sendPacket = null;
        int       sendedNum  = 0;

        while (m_Thread.IsAlive)
        {
            try
            {
                Thread.Sleep(10);
                if (m_ConnectState == EConnectState.PostConnecting)
                {
                    databytes = null;
                    recvedNum = 0;
                    if (sendPacket != null)
                    {
                        sendPacket.DestroyClass();
                        sendPacket = null;
                    }
                    sendedNum = 0;
                    ConnectServer();
                }
                if (m_ConnectState == EConnectState.Connected)
                {
                    string errorText = null;
                    bool   bWaiting  = false;
                    do
                    {
                        errorText = RecvAll(ref headbytes, ref databytes, ref recvedNum, ref bWaiting);
                    }while (errorText == null && !bWaiting);
                    if (errorText == null)
                    {
                        object privateLockObject;
                        Monitor.Enter(privateLockObject = m_PrivateLockObject);
                        try
                        {
                            while (m_SendQueue.Count > 0 || sendPacket != null)
                            {
                                if (sendPacket != null)
                                {
                                    errorText = SendAll(sendPacket, ref sendedNum);
                                    if (sendedNum == sendPacket.GetOffset())
                                    {
                                        sendPacket.DestroyClass();
                                        sendPacket = null;
                                    }
                                }
                                if (errorText != null || sendPacket != null || m_SendQueue.Count <= 0)
                                {
                                    break;
                                }
                                sendedNum  = 0;
                                sendPacket = m_SendQueue.Dequeue();
                                sendPacket.SetHeadLength();
                            }
                        }
                        finally
                        {
                            Monitor.Exit(privateLockObject);
                        }
                    }
                    if (errorText != null)
                    {
                        Debug.LogError(errorText);
                        object privateLockObject;
                        Monitor.Enter(privateLockObject = m_PrivateLockObject);
                        try
                        {
                            if (m_ConnectState != EConnectState.PostConnecting)
                            {
                                m_ConnectState     = EConnectState.Disconnected;
                                m_bNetStateChanged = true;
                                //GameDll.CGameProcedure.s_EventManager.OnNetStateChanged.SafeInvoke((int)NetworkProtol.Tcp, (int)m_ConnectState);
                            }
                        }
                        finally
                        {
                            Monitor.Exit(privateLockObject);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.LogError(ex.Message + ex.StackTrace);
                object privateLockObject;
                Monitor.Enter(privateLockObject = m_PrivateLockObject);
                try
                {
                    if (m_ConnectState != EConnectState.PostConnecting)
                    {
                        m_ConnectState     = EConnectState.Disconnected;
                        m_bNetStateChanged = true;
                        //GameDll.CGameProcedure.s_EventManager.OnNetStateChanged.SafeInvoke((int)NetworkProtol.Tcp, (int)m_ConnectState);
                    }
                }
                finally
                {
                    Monitor.Exit(privateLockObject);
                }
            }
        }
        m_Thread.Abort();
        m_Thread.Join();
    }
示例#13
0
        ///////////////////////////////////////////////////////////////////////////////////////
        // function private

        private void BeginConnect()
        {
            try
            {
                if (socket != null)
                {
                    if (socket.Connected)
                    {
                        Debug.Log("BeginConnect() Already Connected.?");
                        //socket.Shutdown(SocketShutdown.Both);
                    }
                    socket.Close();
                }

                string        convertedHost   = startParam.hostname;
                AddressFamily convertedFamily = AddressFamily.InterNetwork;
#if !UNITY_STANDALONE
                CIPv6Supporter ipv6Supporter = new CIPv6Supporter();
                ipv6Supporter.ConvertHostInfo(startParam.hostname, out convertedHost, out convertedFamily);
#endif

                socket         = new Socket(convertedFamily, SocketType.Stream, ProtocolType.Tcp);
                socket.NoDelay = true;
#if UNITY_STANDALONE
                const int IOC_VENDOR = 0x18000000;
                const int IOC_IN     = -2147483648; //0x80000000;
                const int SIO_TCP_SET_ACK_FREQUENCY = IOC_IN | IOC_VENDOR | 23;

                byte[] outvalue = BitConverter.GetBytes(0);
                socket.IOControl(SIO_TCP_SET_ACK_FREQUENCY, BitConverter.GetBytes((int)1), outvalue);
#endif

                socket.BeginConnect(convertedHost, startParam.port, asyncCallbackConnect, socket);

                ConnectState = EConnectState.ConnectBegin;

                Debug.Log("BeginConnect().!");
            }
            catch (Exception ex)
            {
                Debug.Log("BeginConnect() Exception " + ex.ToString());

                switch (ConnectState)
                {
                case EConnectState.None:
                {
                    // 재접속이 아닐 경우만 함수를 통해 클라에 알리자
                    ErrorTypeJoinServerComplete = ErrorType.ErrorType_TCPConnectFailure;
                }
                break;

                case EConnectState.Reconnecting:
                {
                    ConnectState = EConnectState.ReconnectFail;
                }
                break;
                }

                try
                {
                    if (socket != null)
                    {
                        socket.Close();
                    }
                }
                catch (Exception)
                {
                    Debug.Log("BeginConnect() socket shutdown Exception " + ex.ToString());
                }

                return;
            }
        }
示例#14
0
    private string RecvAll(ref HeaderBytes msgHeader, ref DataBytes msgData, ref int nRecved, ref bool bWaiting)
    {
        string result;

        if (msgData == null)
        {
            SocketError socketError;
            int         recveNum = m_Socket.Receive(msgHeader.Bytes, nRecved, msgHeader.Bytes.Length - nRecved, SocketFlags.None, out socketError);
            if (recveNum < 0)
            {
                result = "消息头小于0";
                return(result);
            }
            if (socketError != SocketError.Success && socketError != SocketError.WouldBlock)
            {
                result             = "网络错误:" + socketError.ToString();
                m_ConnectState     = EConnectState.PostConnecting;
                m_bNetStateChanged = true;
                //GameDll.CGameProcedure.s_EventManager.OnNetStateChanged.SafeInvoke((int)NetworkProtol.Tcp, (int)m_ConnectState);
                return(result);
            }
            if (recveNum == 0)
            {
                bWaiting = true;
                result   = null;
                return(result);
            }
            nRecved += recveNum;
            if (nRecved == msgHeader.Bytes.Length)
            {
                ushort msgType   = 0;
                ushort msgLength = 0;
                if (!WfPacket.ParseHeader(msgHeader.Bytes, ref msgType, ref msgLength))
                {
                    result = string.Concat(new object[]
                    {
                        "error ParseHeader type:",
                        msgType,
                        "len:",
                        msgLength
                    });
                    return(result);
                }
                if (msgLength < msgHeader.Bytes.Length)
                {
                    result = string.Concat(new object[]
                    {
                        "error ParseHeader < msglen:", msgLength, "headerLength:", msgHeader.Bytes.Length
                    });
                    return(result);
                }
                if (msgLength == msgHeader.Bytes.Length)
                {
                    //这里虽然只有一个是一个很简单的只带有消息头的消息,例如心跳,但是我依然用了完整消息大小
                    msgData = PooledClassManager <DataBytes> .CreateClass();

                    msgData.SetBytes(msgLength + 1);
                    Array.Copy(msgHeader.Bytes, 0, msgData.GetBytes(), 0, msgHeader.Bytes.Length);
                    WfPacket item = PooledClassManager <WfPacket> .CreateClass();

                    item.InitRead(msgData);
                    msgData = null;
                    nRecved = 0;
                    object privateLockObject;
                    Monitor.Enter(privateLockObject = m_PrivateLockObject);
                    try
                    {
                        m_RecvQueue.Enqueue(item);
                    }
                    finally
                    {
                        Monitor.Exit(privateLockObject);
                    }
                }
                else
                {
                    msgData = PooledClassManager <DataBytes> .CreateClass();

                    msgData.SetBytes(msgLength);
                    Array.Copy(msgHeader.Bytes, 0, msgData.GetBytes(), 0, msgHeader.Bytes.Length);
                    nRecved = msgHeader.Bytes.Length;
                }
            }
        }
        if (msgData != null)
        {
            SocketError socketError;
            int         recveNum = m_Socket.Receive(msgData.GetBytes(), nRecved, msgData.GetLength() - nRecved, SocketFlags.None, out socketError);
            //Debug.Log("底层函数接收数据:" + socketError.ToString());
            if (recveNum < 0)
            {
                result = "ReceiveData < 0";
                return(result);
            }
            if (socketError != SocketError.Success && socketError != SocketError.WouldBlock)
            {
                result = "ReceiveData Failed";
                return(result);
            }
            if (recveNum == 0)
            {
                bWaiting = true;
                result   = null;
                return(result);
            }
            nRecved += recveNum;
            if (nRecved > msgData.GetLength())
            {
                result = "ReceiveData IO error";
                return(result);
            }
            if (nRecved == msgData.GetLength())
            {
                WfPacket item = PooledClassManager <WfPacket> .CreateClass();

                item.InitRead(msgData);
                msgData = null;
                nRecved = 0;
                object privateLockObject;
                Monitor.Enter(privateLockObject = m_PrivateLockObject);
                try
                {
                    m_RecvQueue.Enqueue(item);
                }
                finally
                {
                    Monitor.Exit(privateLockObject);
                }
            }
            else
            {
                bWaiting = true;
            }
        }
        result = null;
        return(result);
    }
示例#15
0
        private void BeginSend()
        {
            try
            {
                if (IsConnected == false)
                {
                    Debug.Log("BeginSend() : IsConnected() == false");
                    return;
                }

                if (ConnectState != EConnectState.Connected)
                {
                    // 서버와의 기본 통신까지 끝난 상태여야 패킷을 보낼수 있다.
                    Debug.Log("BeginSend() : ConnectState != ReconnectState.Connected");

                    return;
                }

                Message msg = null;

                lock ( csSend )
                {
                    if (queSend.Count == 0)
                    {
                        return;
                    }

                    msg = queSend.Peek();
                }

                switch (msg.RmiContextValue)
                {
                case (byte)RmiContext.ReliableCompress:
                {
                    ZipHelper.CompressToMessage(ref msg);
                }
                break;

                case (byte)RmiContext.FastEncryp:
                {
                    Crypto.XOREncrypt(msg.buffer, BasicType.HEADSIZE, msg.Length);
                }
                break;

                case (byte)RmiContext.FastEncrypCompress:
                {
                    Crypto.XOREncrypt(msg.buffer, BasicType.HEADSIZE, msg.Length);

                    ZipHelper.CompressToMessage(ref msg);
                }
                break;
                }

                ++SequenceNumSend;
                msg.SequenceNum = SequenceNumSend;

                socket.BeginSend(msg.buffer, 0, msg.Length, SocketFlags.None, asyncCallbackSend, socket);
            }
            catch (Exception ex)
            {
                Debug.Log("BeginSend() exception : " + ex.ToString());

                try
                {
                    if (socket != null)
                    {
                        socket.Close();
                    }
                }
                catch (Exception)
                {
                    Debug.Log("BeginSend() socket shutdown Exception " + ex.ToString());
                }

                ConnectState = EConnectState.None;
            }
        }
示例#16
0
 public NetworkConnection(INetworkClient networkclient)
 {
     _rttTime       = 3.0f;
     _networkclient = networkclient;
     _eConnectState = EConnectState.Null;
 }
示例#17
0
    void ProcessRecvBuffer(Message message)
    {
        Log.InfoFormat("[ProcessRecvBuffer] receive message seq = {0} ack = {1} ctrl = {2}", message.seq, message.ack, message.ctrl);
        if (message.ctrl == (byte)ESAFlag.Ctrl)// ctrl message
        {
            Log.InfoFormat("[Info] ProcessRecvBuffer Receive Ctrl Message");
            //  receive syn & ack message
            if (message.syn == 1)
            {
                if (_eConnectState == EConnectState.SYN_SENT)
                {
                    _base   = (byte)(message.ack + 1);
                    _svrSeq = message.seq;
                    OnReceiveAck();
                    SendCtrlAck();
                    _eConnectState = EConnectState.ESTABLISHED;
                    Log.InfoFormat("ProcessRecvBuffer _eConnectState from {0} to {1}", EConnectState.SYN_SENT, _eConnectState);
                }
                else
                {
                    Log.InfoFormat("[Info] Receive syn with _eConnectState = {0}", _eConnectState);
                }
            }
            else if (message.fin == 1)
            {
                if (_eConnectState == EConnectState.FIN_WAIT_2)
                {
                    SendCtrlAck();
                    _eConnectState = EConnectState.TIME_WAIT;
                    Log.InfoFormat("[Info] Receive Fin, Send Ack, _eConnectState from {0} to {1}", EConnectState.FIN_WAIT_2, _eConnectState);
                    _finCountdownId = CountdownTimer.Instance.StartTimer(3, FinCountdown);
                }
                else
                {
                    Log.InfoFormat("[Info] Receive Fin while _eConnectState = {0}", _eConnectState);
                }
            }
            else if (_eConnectState == EConnectState.FIN_WAIT_1)// receive ack message for fin
            {
                _base = (byte)(message.ack + 1);
                OnReceiveAck();
                _eConnectState = EConnectState.FIN_WAIT_2;
                Log.InfoFormat("[Info] Receive Ack Send Nothing, _eConnectState = {0}", _eConnectState);
            }
        }
        else if (message.ctrl == (byte)ESAFlag.Seq) // seq
        {
            Log.InfoFormat("[Info] ProcessRecvBuffer Receive seq message");
            if (message.seq != GetSvrSeq())
            {
                // ignore receiver 's message
                Log.InfoFormat("[Info] Receive message.seq = {0} != _svrSeq {1}, discard", message.seq, _svrSeq);
                ResendAck();
                return;
            }
            // receive message correctly
            // handle message
            // set server seq
            _svrSeq = message.seq;
            Log.InfoFormat("[Info] ProcessRecvBuffer message.seq = {0}", message.seq);

            SendAck();
            _networkclient.PostMessage(message);
        }
        else if (message.ctrl == (byte)ESAFlag.Ack) //ack
        {
            var ack = message.ack;
            _base = (byte)(ack);

            Log.InfoFormat("[Info] ProcessRecvBuffer Receive ack message ack = {0}", ack);
            OnReceiveAck();
        }
    }
示例#18
0
        /*
         * Socket.BeginReceive() 바인딩 되어 Packet 을 받게 되면 호출
         * P.S : host thread 에서 호출됨
         */
        private void OnCallbackRecv(IAsyncResult iar)
        {
            try
            {
                Socket socketTemp = (Socket)iar.AsyncState;

                if (socketTemp.Connected == false)
                {
                    Debug.Log("NetClient.OnCallbackRecv() : socketTemp.connected == false");

                    //if (socket != null)
                    //    socket.Close();
                    return;
                }

                int iReadSize = socketTemp.EndReceive(iar);

                if (iReadSize > 0)
                {
                    buffRecvSize += iReadSize;

                    /*
                     *          패킷이 나누어져서 오거나
                     *          2개 이상의 패킷이 하나로 올수 있어서 체크한다(네이글 알골리즘)
                     */
                    while (buffRecvSize >= sizeof(int))
                    {
                        Int32 packetLength = 0;
                        packetLength = BitConverter.ToInt32(bufferRecv, 0);

                        if (buffRecvSize >= packetLength)
                        {
                            Message msgRecv = new Message();
                            Buffer.BlockCopy(bufferRecv, 0, msgRecv.buffer, 0, packetLength);

                            buffRecvSize -= packetLength;
                            if (buffRecvSize >= sizeof(int))
                            {
                                // 전달할 부분을 빼고 데이터가 남았다면 앞부분으로 당김
                                Buffer.BlockCopy(bufferRecv, packetLength, bufferRecv, 0, buffRecvSize);
                            }

                            switch (msgRecv.RmiContextValue)
                            {
                            case (byte)RmiContext.ReliableCompress:
                            {
                                ZipHelper.UncompressToMessage(ref msgRecv);
                            }
                            break;

                            case (byte)RmiContext.FastEncryp:
                            {
                                Crypto.XOREncrypt(msgRecv.buffer, BasicType.HEADSIZE, packetLength);
                            }
                            break;

                            case (byte)RmiContext.FastEncrypCompress:
                            {
                                ZipHelper.UncompressToMessage(ref msgRecv);

                                Crypto.XOREncrypt(msgRecv.buffer, BasicType.HEADSIZE, msgRecv.Length);
                            }
                            break;
                            }

                            // HeartBit 회신
                            if (msgRecv.ID < 0)
                            {
                                OnReceiveServerMessage(msgRecv);

                                continue;
                            }

                            lock ( csRecv )
                            {
                                // 클라 쓰레드로 전달
                                queRecv.Enqueue(msgRecv);
                            }
                        }
                        else
                        {
                            // 온전한 패킷을 구성하기에 충분한 데이터가 없음. loop를 빠져나간다.
                            break;
                        }
                    }
                }
                else if (iReadSize == 0)
                {
                    Debug.Log("OnCallbackRecv() ReadSize == 0 : Socket Close");

                    // LeaveServer 가 FrameMove 에서 호출되면 Socket 종료처리 한다.
                    ErrorTypeLeaveServer = ErrorType.ErrorType_DisconnectFromRemote;

                    ConnectState = EConnectState.None;

                    if (socket != null)
                    {
                        socket.Close();
                    }

                    return;
                }

                // 메세지 리시브 대기
                if (IsConnected)
                {
                    socket.BeginReceive(bufferRecv, buffRecvSize, bufferRecv.Length - buffRecvSize, SocketFlags.None, asyncCallbackRecv, socket);
                }
            }
            catch (Exception ex)
            {
                Debug.Log("OnCallbackRecv exception : " + ex.ToString());

                try
                {
                    if (socket != null)
                    {
                        socket.Close();
                    }
                }
                catch (Exception exSub)
                {
                    Debug.Log("OnCallbackRecv socket shutdown exception : " + exSub.ToString());
                }
            }
        }
示例#19
0
        private void OnReceiveServerMessage(Message msg)
        {
            switch (msg.ID)
            {
            case BasicType.PACKETID_HEART_BIT:
            {
                MessageMarshal.Read(msg, out _PingMS);
                RmiSend(RmiContext.Reliable, BasicType.PACKETID_HEART_BIT, msg);
            }
            break;

            case BasicType.PACKETID_SC_HOSTID_INFO:
            {
                if (hostID == HostID_None)
                {
                    // 신규접속 성공 보냄
                    Int64 tempHost = HostID_None;
                    MessageMarshal.Read(msg, out tempHost);
                    hostID = tempHost;
                    UInt32 xorKey0, xorKey1, xorKey2;
                    MessageMarshal.Read(msg, out xorKey0);
                    MessageMarshal.Read(msg, out xorKey1);
                    MessageMarshal.Read(msg, out xorKey2);
                    Crypto.XOR_KEY.Clear();
                    Crypto.XOR_KEY.Add(xorKey0);
                    Crypto.XOR_KEY.Add(xorKey1);
                    Crypto.XOR_KEY.Add(xorKey2);

                    Debug.Log(string.Format("OnReceiveServerMessage(HostInfo) Read( hostID({0}) )", hostID));

                    Message msgSend = new Message();
                    msgSend.ID = BasicType.PACKETID_CS_HOSTID_RECV;
                    MessageMarshal.Write(msgSend, hostID);

                    ++SequenceNumSend;
                    msgSend.SequenceNum = SequenceNumSend;

                    msgSend.WriteEnd();
                    //RmiSend( RmiContext.Reliable, BasicType.PACKETID_CS_HOSTID_RECV, msgSend );

                    socket.BeginSend(msgSend.buffer, 0, msgSend.Length, SocketFlags.None, asyncCallbackSend, socket);
                }
                else
                {
                    // 재접속 처리 요청
                    Message msgSend = new Message();
                    msgSend.ID = BasicType.PACKETID_CS_HOSTID_RECONNECT;

                    ++SequenceNumSend;
                    msgSend.SequenceNum = SequenceNumSend;

                    MessageMarshal.Write(msgSend, hostID);
                    msgSend.WriteEnd();

                    Int64 remoteID;
                    MessageMarshal.Read(msg, out remoteID);

                    Debug.Log(string.Format("OnReceiveServerMessage(HostInfoRecon) hostID({0}), Read( hostID({1}) )", hostID, remoteID));

                    try
                    {
                        if (socket.Connected)
                        {
                            // 재접속 중이라 쌓여있는 패킷이 있을수 있어 다이렉트로 회신한다.
                            socket.BeginSend(msgSend.buffer, 0, msgSend.Length, SocketFlags.None, asyncCallbackSend, socket);
                        }
                    }
                    catch
                    {
                        try
                        {
                            if (socket != null)
                            {
                                socket.Close();
                            }
                        }
                        catch (Exception ex)
                        {
                            Debug.Log("OnReceiveServerMessage() socket shutdown Exception " + ex.ToString());
                        }
                    }
                }
            }
            break;

            case BasicType.PACKETID_SC_CONNECT_SUCCESS:
            {
                Debug.Log("OnReceiveServerMessage() : PACKETID_SC_CONNECT_SUCCESS");
                ConnectState = EConnectState.Connected;
                ErrorTypeJoinServerComplete = ErrorType.ErrorType_Ok;

                BeginSend();
            }
            break;

            case BasicType.PACKETID_SC_RECONNECT_SUCCESS:
            {
                ConnectState = EConnectState.Connected;

                Debug.Log(string.Format("OnReceiveServerMessage() " + BasicType.PACKETID_SC_RECONNECT_SUCCESS.ToString()));
            }
            break;

            case BasicType.PACKETID_SC_RECONNECT_FAIL:
            {
                Debug.Log(string.Format("OnReceiveServerMessage() " + BasicType.PACKETID_SC_RECONNECT_FAIL.ToString()));

                /*
                 * 재접속 실패일 경우 클라에서는 접속중으로 인식하기 때문에 접속 종료를 알리자
                 * LeaveServer 가 FrameMove 에서 호출되면 Socket 종료처리 한다.
                 */
                ErrorTypeLeaveServer = ErrorType.ErrorType_ReconnectFail;
            }
            break;
            }
        }
示例#20
0
        /*
         * 클라이언트 Tick 에서 호출해주어야 한다.
         * Recv 된 패킷이 queue 되어 있을 경우 1 frame 당 1개의 packet 을 OnPacketReceive() 을 통해 전달 해준다
         */
        public void FrameMove()
        {
            if (startParam == null || startParam.IsValid == false)
            {
                return;
            }

            if (ErrorTypeJoinServerComplete != ErrorType.ErrorType_None)
            {
                startParam.OnJoinServerComplete(ErrorTypeJoinServerComplete);
                ErrorTypeJoinServerComplete = ErrorType.ErrorType_None;
            }
            if (ErrorTypeLeaveServer != ErrorType.ErrorType_None)
            {
                startParam.OnLeaveServer(ErrorTypeLeaveServer);
                ErrorTypeLeaveServer = ErrorType.ErrorType_None;

                Disconnect();
            }

            try
            {
                if (socket != null && socket.Connected == false)
                {
                    // 재접속.?
                    switch (ConnectState)
                    {
                    case EConnectState.Connected:
                    {
                        tmReconnectStart = DateTime.Now;
                        ConnectState     = EConnectState.Reconnecting;

                        BeginConnect();
                    }
                    break;

                    case EConnectState.ReconnectFail:
                    {
                        var tmValue = DateTime.Now - tmReconnectStart;
                        if (tmValue.TotalSeconds >= 60)
                        {
                            // 재접속 연결 시간이 지나면 종료하자(1분)
                            ErrorTypeLeaveServer = ErrorType.ErrorType_ReconnectFail;
                            ConnectState         = EConnectState.ReconnectClose;

                            break;
                        }

                        ConnectState = EConnectState.Reconnecting;
                        BeginConnect();
                    }
                    break;
                    }

                    return;
                }
            }
            catch (Exception ex)
            {
                Debug.Log("FrameMove exception : " + ex.ToString());
            }

            List <Message> vecRecv = new List <Message>();

            lock ( csRecv )
            {
                while (queRecv.Count > 0)
                {
                    vecRecv.Add(queRecv.Dequeue());
                }
            }

            if (vecRecv.Count > 0)
            {
                foreach (var bufferRecv in vecRecv)
                {
                    bool IsStub = false;
                    foreach (var stub in listRmiStub)
                    {
                        if (stub.ProcessReceivedMessage(bufferRecv))
                        {
                            IsStub = true;
                            break;
                        }
                    }

                    if (IsStub == false && startParam.OnReceiveMessage != null)
                    {
                        startParam.OnReceiveMessage(bufferRecv);
                        IsStub = true;
                    }

                    if (IsStub == false && listRmiStub.Count > 0)
                    {
                        Debug.Log("function that a user did not create has been called. : listRmiStub.Count > 0");
                    }
                }
            }
        }
示例#21
0
        public void Update(float deltaTime)
        {
            if (mConnectState == EConnectState.Connected)  // 已连接状态
            {
                DealWithMsg();

                if (mRecvResult != null)
                {
                    if (mReceiveCount > mMaxReceiveCount && Time.time > mReceiveOverTime)
                    {
                        DebugEx.LogError("recv data over 200, so close network");
                        Close();
                        return;
                    }

                    ++mReceiveCount;

                    if (mRecvResult.IsCompleted)
                    {
                        try
                        {
                            Int32 readSize = mClient.GetStream().EndRead(mRecvResult);  // 从流中读取的字节数
                            mRecvPos += readSize;
                            if (readSize == 0)
                            {
                                DebugEx.LogError("can't recv data now, so close network");
                                Close();
                                return;
                            }
                        }
                        catch (System.Exception exception)
                        {
                            DebugEx.LogError(exception.ToString());
                            Close();
                            return;
                        }

                        OnDataReceived();

                        if (mClient != null)
                        {
                            try
                            {
                                // 从流中读取数据存放到mRecvBuffer中,从mRecvPos位置开始存放
                                mRecvResult      = mClient.GetStream().BeginRead(mRecvBuffer, mRecvPos, mRecvBuffer.Length - mRecvPos, null, null);
                                mReceiveOverTime = Time.time + mMaxReceiveDuration;
                                mReceiveCount    = 0;
                            }
                            catch (System.Exception exception)
                            {
                                DebugEx.LogError(exception.ToString());
                                Close();
                                return;
                            }
                        }
                    }
                }
                if (mClient != null && mClient.Connected == false)
                {
                    DebugEx.LogError("client is close by system, so close it now");
                    Close();
                    return;
                }
            }
            else if (mConnectState == EConnectState.Connecting)  // 正在连接状态
            {
                if (mConnectCount > mMaxConnectCount && Time.time > mConnectOverTime)
                {
                    DebugEx.LogError("can't connect, so close network");
                    mConnectResult = null;
                    OnConnectError(mClient, null);
                    return;
                }
                // 记录连接历经的帧数
                ++mConnectCount;
                if (mConnectResult.IsCompleted)  // 连接完成
                {
                    mConnectState = EConnectState.Connected;

                    mConnectResult = null;

                    if (mClient.Connected)
                    {
                        try
                        {
                            mClient.NoDelay = true;

                            mClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 2000);

                            mClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 2000);

                            mClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

                            mRecvResult = mClient.GetStream().BeginRead(mRecvBuffer, 0, mRecvBuffer.Length, null, null);

                            mReceiveOverTime = Time.time + mMaxReceiveDuration;

                            mReceiveCount = 0;

                            OnConnected(mClient, null);
                        }
                        catch (Exception exception)
                        {
                            DebugEx.LogError(exception.ToString());
                            Close();
                            return;
                        }
                    }
                    else
                    {
                        OnConnectError(mClient, null);
                    }
                }
            }
            else
            {
                Connect();
            }
        }