Beispiel #1
0
        /// <summary>
        ///數據接收處理函數
        /// </summary>
        /// <param name="iar">異步Socket</param>
        protected virtual void RecvData(IAsyncResult iar)
        {
            Socket remote = (Socket)iar.AsyncState;

            try
            {
                String receivedData = String.Empty;
                int    recv         = remote.EndReceive(iar);
                //正常的退出
                if (recv == 0)
                {
                    _session.TypeOfExit = Session.ExitType.NormalExit;
                    if (DisConnectedServer != null)
                    {
                        DisConnectedServer(this, new NetEventArgs(_session));
                    }
                    return;
                }
                if (HeadLength)
                {
                    byte[] Bytes = new byte[_recvDataBuffer.Length - 4];
                    Array.Copy(_recvDataBuffer, 4, Bytes, 0, _recvDataBuffer.Length - 4);
                    receivedData = _coder.GetEncodingString(Bytes, recv);
                }
                else
                {
                    receivedData = _coder.GetEncodingString(_recvDataBuffer, recv);
                }
                //通過事件發布收到的報文
                if (ReceivedDatagram != null)
                {
                    //通過報文解析器分析出報文
                    //如果定義了報文的尾標記,需要處理報文的多種情況
                    if (_resolver != null)
                    {
                        if (_session.Datagram != null &&
                            _session.Datagram.Length != 0)
                        {
                            //加上最後一次通訊剩餘的報文片斷
                            receivedData = _session.Datagram + receivedData;
                        }
                        string[] recvDatagrams = _resolver.Resolve(ref receivedData);

                        foreach (string newDatagram in recvDatagrams)
                        {
                            //因為需要保證多個不同報文獨立存在
                            ICloneable copySession   = (ICloneable)_session;
                            Session    clientSession = (Session)copySession.Clone();
                            clientSession.Datagram = newDatagram;
                            //發布一個報文消息
                            ReceivedDatagram(this, new NetEventArgs(clientSession));
                        }
                        //剩餘的代碼片斷,下次接收的時候使用
                        _session.Datagram = receivedData;
                    }
                    //沒有定義報文的尾標記,直接交給消息訂閱者使用
                    else
                    {
                        ICloneable copySession   = (ICloneable)_session;
                        Session    clientSession = (Session)copySession.Clone();
                        clientSession.Datagram = receivedData;
                        ReceivedDatagram(this, new NetEventArgs(clientSession));
                    }
                }//end of if(ReceivedDatagram != null)
                //繼續接收數據
                _session.ClientSocket.BeginReceive(_recvDataBuffer, 0, DefaultBufferSize, SocketFlags.None,
                                                   new AsyncCallback(RecvData), _session.ClientSocket);
            }
            catch (SocketException ex)
            {
                //客戶端退出
                if (10054 == ex.ErrorCode)
                {
                    //服務器強制的關閉連接,強制退出
                    _session.TypeOfExit = Session.ExitType.ExceptionExit;
                    if (DisConnectedServer != null)
                    {
                        DisConnectedServer(this, new NetEventArgs(_session));
                    }
                }
                else
                {
                    throw (ex);
                }
            }
            catch (ObjectDisposedException ex)
            {
                //這裡的實現不夠優雅
                //當調用CloseSession()時,會結束數據接收,但是數據接收
                //處理中會調用int recv = client.EndReceive(iar);
                //就訪問了CloseSession()已經處置的對象
                //我想這樣的實現方法也是無傷大雅的。
                if (ex != null)
                {
                    ex = null;
                    //DoNothing;
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// 接受数据完成处理函数,异步的特性就体现在这个函数中,
        /// 收到数据后,会自动解析为字符串报文
        /// </summary>
        /// <param name="iar">目标客户端Socket</param>
        protected virtual void ReceiveData(IAsyncResult iar)
        {
            Socket client = (Socket)iar.AsyncState;

            try
            {
                //如果两次开始了异步的接收,所以当客户端退出的时候
                //会两次执行EndReceive
                string receivedData = String.Empty;
                int    recv         = client.EndReceive(iar);
                if (recv == 0)
                {
                    //正常的关闭
                    CloseClient(client, Session.ExitType.NormalExit);
                    return;
                }
                if (HeadLength)
                {
                    byte[] Bytes = new byte[_recvDataBuffer.Length - 4];
                    Array.Copy(_recvDataBuffer, 4, Bytes, 0, _recvDataBuffer.Length - 4);
                    receivedData = _coder.GetEncodingString(Bytes, recv);
                }
                else
                {
                    receivedData = _coder.GetEncodingString(_recvDataBuffer, recv);
                }
                //发布收到数据的事件
                if (RecvData != null)
                {
                    Session sendDataSession = FindSession(client);

                    Debug.Assert(sendDataSession != null);
                    //如果定义了报文的尾标记,需要处理报文的多种情况
                    if (_resolver != null)
                    {
                        if (sendDataSession.Datagram != null &&
                            sendDataSession.Datagram.Length != 0)
                        {
                            //加上最后一次通讯剩余的报文片断
                            receivedData = sendDataSession.Datagram + receivedData;
                        }
                        string[] recvDatagrams = _resolver.Resolve(ref receivedData);

                        foreach (string newDatagram in recvDatagrams)
                        {
                            //深拷贝,为了保持Datagram的对立性
                            ICloneable copySession   = (ICloneable)sendDataSession;
                            Session    clientSession = (Session)copySession.Clone();
                            clientSession.Datagram = newDatagram;
                            //发布一个报文消息
                            RecvData(this, new NetEventArgs(clientSession));
                        }
                        //剩余的代码片断,下次接收的时候使用
                        sendDataSession.Datagram = receivedData;
                        if (sendDataSession.Datagram.Length > MaxDatagramSize)
                        {
                            sendDataSession.Datagram = null;
                        }
                    }
                    //没有定义报文的尾标记,直接交给消息订阅者使用
                    else
                    {
                        ICloneable copySession   = (ICloneable)sendDataSession;
                        Session    clientSession = (Session)copySession.Clone();
                        clientSession.Datagram = receivedData;
                        RecvData(this, new NetEventArgs(clientSession));
                    }
                }//end of if(RecvData!=null)
                //继续接收来自来客户端的数据
                client.BeginReceive(_recvDataBuffer, 0, _recvDataBuffer.Length, SocketFlags.None,
                                    new AsyncCallback(ReceiveData), client);
            }
            catch (SocketException ex)
            {
                //客户端退出
                if (10054 == ex.ErrorCode)
                {
                    //客户端强制关闭
                    CloseClient(client, Session.ExitType.ExceptionExit);
                }
            }
            catch (ObjectDisposedException ex)
            {
                //这里的实现不够优雅
                //当调用CloseSession()时,会结束数据接收,但是数据接收
                //处理中会调用int recv = client.EndReceive(iar);
                //就访问了CloseSession()已经处置的对象
                //我想这样的实现方法也是无伤大雅的.
                if (ex != null)
                {
                    ex = null;
                    //DoNothing;
                }
            }
        }