/// <summary> /// 接受数据完成处理函数,异步的特性就体现在这个函数中, /// 收到数据后,会自动解析为字符串报文 /// </summary> /// <param name="iar">目标客户端Socket</param> /// protected virtual void ReceiveData(IAsyncResult iar) { Socket client = (Socket)iar.AsyncState; try { //如果两次开始了异步的接收,所以当客户端退出的时候 //会两次执行EndReceive int recv = client.EndReceive(iar); if (recv == 0) { //正常的关闭 CloseClient(client, Session.ExitType.NormalExit); return; } string receivedData; receivedData = _coder.GetEncodingString(_recvDataBuffer, 0, recv); if (RecvData != null) { Session sendDataSession = FindSession(client); ICloneable copySession = (ICloneable)sendDataSession; Session clientSession = (Session)copySession.Clone(); clientSession.Datagram = receivedData; RecvData(this, new NetEventArgs(clientSession)); } //继续接收来自来客户端的数据 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; } } }
/// <summary> /// 数据接收处理函数 /// </summary> /// <param name="iar">异步Socket</param> protected virtual void RecvData(IAsyncResult iar) { Socket remote = (Socket)iar.AsyncState; try { int recv = remote.EndReceive(iar); //正常的退出 if (recv == 0) { _session.TypeOfExit = Session.ExitType.NormalExit; if (DisConnectedServer != null) { DisConnectedServer(this, new NetEventArgs(_session)); } return; } string receivedData; if (_recvDataBuffer[0] == 0x55) { receivedData = _coder.GetEncodingString(_recvDataBuffer, 1, recv - 1); } else { string fileName = this._coder.GetEncodingString(_recvDataBuffer, 6, _recvDataBuffer[1] - 1); _coder.SaveFile(_filePath + fileName, _recvDataBuffer); receivedData = "Receive File:" + fileName + "##"; } //通过事件发布收到的报文 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) { //Need Deep Copy.因为需要保证多个不同报文独立存在 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; } } }