/// <summary> /// 接受数据完成处理函数,异步的特性就体现在这个函数中, /// 收到数据后,会自动解析为字符串报文 /// </summary> /// <param name="iar">目标客户端Socket</param> protected virtual void ReceiveData(IAsyncResult iar) { //iar.AsyncState Socket client = (Socket)iar.AsyncState; try { //如果两次开始了异步的接收,所以当客户端退出的时候 //会两次执行EndReceive int recv = client.EndReceive(iar); if (recv == 0) { //正常的关闭 CloseClient(client, Session.ExitType.NormalExit); return; } if (RecvData != null) { Session sendDataSession = FindSession(client);//查找客户端 Debug.Assert(sendDataSession != null); if (sendDataSession.RecordSize == 0) { byte[] headSize = YH(_recvDataBuffer, 4); uint copysize = BitConverter.ToUInt32(headSize, 0); sendDataSession.DataMaxSize = copysize+4; //这里+4忽略是因为协议上 对方忘记计算了一个dword 所以我接受直接多接收就好了。 sendDataSession.DataG = null; } uint len = sendDataSession.DataMaxSize - (uint)sendDataSession.RecordSize; if (len >= FenbaoSize) { //如果大于等于255 就直接读255 。 byte[] temp = new byte[255]; if (sendDataSession.RecordSize == 0) { sendDataSession.DataG = _recvDataBuffer.Take(FenbaoSize).ToArray(); } else { sendDataSession.DataG = sendDataSession.DataG.Concat(_recvDataBuffer.Take(FenbaoSize).ToArray()).ToArray(); } sendDataSession.RecordSize = sendDataSession.RecordSize + FenbaoSize; }else if (len<FenbaoSize) { //如果小于255 说明也是最后一个包了。 sendDataSession.RecordSize = sendDataSession.RecordSize + (int)len; sendDataSession.DataG=sendDataSession.DataG.Concat(_recvDataBuffer.Take((int)len).ToArray()).ToArray(); } if (sendDataSession.RecordSize == sendDataSession.DataMaxSize)//如果接收完毕。就拷贝过来,然后初始化 最后发布数据事件 { ICloneable copySession = (ICloneable)sendDataSession;//拷贝 Session clientSession = (Session)copySession.Clone(); clientSession.DataG = sendDataSession.DataG;//给数据 sendDataSession.RecordSize = 0;//初始化 sendDataSession.DataMaxSize = 0; RecvData(this, new NetEventArgs(clientSession));//发布收到数据的事件 } } client.BeginReceive(_recvDataBuffer, 0, FenbaoSize, SocketFlags.None, new AsyncCallback(ReceiveData), client);//继续监听 } catch (SocketException ex) { //客户端退出 if (10054 == ex.ErrorCode) { //客户端强制关闭 CloseClient(client, Session.ExitType.ExceptionExit); } } catch (ObjectDisposedException ex) { if (ex != null) { ex = null; //DoNothing; } } }
貌似异步必须分包接收?不然有粘包现象? 不知道反正我是这么改的。 如果有学习soket的可以一起交流啊。我很菜~