/// <summary>接收消息</summary> /// <param name="DoResultHandle">运行处理消息函数,应保证不多线程同时访问BinarySocketClient</param> /// <param name="UnknownFaulted">未知错误处理函数</param> public void ReceiveAsync(Action <Action> DoResultHandle, Action <Exception> UnknownFaulted) { Action <Exception> Faulted = ex => { if (!IsRunningValue.Check(b => b) && IsSocketErrorKnown(ex)) { return; } UnknownFaulted(ex); }; Action <Byte[]> CompletedSocket = Buffer => { Action a = () => { if (Buffer.Length < 12) { return; } var SessionId = Buffer[0] | ((Int32)(Buffer[1]) << 8) | ((Int32)(Buffer[2]) << 16) | ((Int32)(Buffer[3]) << 24); var Flag = Buffer[4] | ((Int32)(Buffer[5]) << 8); var Index = Buffer[6] | ((Int32)(Buffer[7]) << 8); var Verification = Buffer[8] | ((Int32)(Buffer[9]) << 8) | ((Int32)(Buffer[10]) << 16) | ((Int32)(Buffer[11]) << 24); Buffer[8] = 0; Buffer[9] = 0; Buffer[10] = 0; Buffer[11] = 0; //Debug.WriteLine(Times.DateTimeUtcWithMillisecondsToString(DateTime.UtcNow) + " Receive SessionId: " + SessionId.ToString("X8") + " Index: " + Index.ToString()); var IsEncrypted = (Flag & 2) != 0; var SecureContext = this.SecureContext; if ((SecureContext != null) != IsEncrypted) { return; } if (IsEncrypted) { var Key = SecureContext.ServerToken.Concat(Cryptography.SHA256(Buffer.Skip(4).Take(4))); var HMACBytes = Cryptography.HMACSHA256Simple(Key, Buffer).Take(4).ToArray(); var HMAC = HMACBytes[0] | ((Int32)(HMACBytes[1]) << 8) | ((Int32)(HMACBytes[2]) << 16) | ((Int32)(HMACBytes[3]) << 24); if (HMAC != Verification) { return; } } else { //如果Flag中不包含ENC,则验证CRC32 if (Cryptography.CRC32(Buffer) != Verification) { return; } //只有尚未连接时可以设定 var Close = false; ConnectionStateValue.Update(v => { if (v == ConnectionState.Connecting) { this.SessionId = SessionId; return(ConnectionState.Connected); } else { if (SessionId != this.SessionId) { Close = true; } return(v); } }); if (Close) { return; } } var Offset = 12; int[] Indices = null; if ((Flag & 1) != 0) { if (Buffer.Length < 14) { return; } var NumIndex = Buffer[Offset] | ((Int32)(Buffer[Offset + 1]) << 8); if (Buffer.Length < 14 + NumIndex * 2) { return; } if (NumIndex > WritingWindowSize) //若Index数量较大,则丢弃包 { return; } Offset += 2; Indices = new int[NumIndex]; for (int k = 0; k < NumIndex; k += 1) { Indices[k] = Buffer[Offset + k * 2] | ((Int32)(Buffer[Offset + k * 2 + 1]) << 8); } Offset += NumIndex * 2; } var Length = Buffer.Length - Offset; if ((Indices != null) && (Indices.Length > 0)) { CookedWritingContext.DoAction(c => { c.Parts.Acknowledge(Indices.First(), Indices.Skip(1), c.WritenIndex); }); } var Pushed = false; var Parts = new List <Byte[]>(); RawReadingContext.DoAction(c => { if (c.Parts.HasPart(Index)) { Pushed = true; return; } Pushed = c.Parts.TryPushPart(Index, Buffer, Offset, Length); if (Pushed) { c.NotAcknowledgedIndices.Add(Index); var Acknowledged = new List <int>(); foreach (var i in c.NotAcknowledgedIndices) { if (c.Parts.IsEqualOrAfter(c.Parts.MaxHandled, i)) { Acknowledged.Add(i); } } foreach (var i in Acknowledged) { c.NotAcknowledgedIndices.Remove(i); } while (true) { var p = c.Parts.TryTakeFirstPart(); if (p == null) { break; } Parts.Add(p.Data); } } }); foreach (var p in Parts) { var ReadBuffer = VirtualTransportClient.GetReadBuffer(); var ReadBufferLength = ReadBuffer.Offset + ReadBuffer.Count; if (p.Length > ReadBuffer.Array.Length - ReadBufferLength) { Faulted(new InvalidOperationException()); return; } Array.Copy(p, 0, ReadBuffer.Array, ReadBufferLength, p.Length); var c = p.Length; while (true) { var r = VirtualTransportClient.Handle(c); if (r.OnContinue) { break; } else if (r.OnCommand) { DoResultHandle(r.Command.HandleResult); var RemainCount = VirtualTransportClient.GetReadBuffer().Count; if (RemainCount <= 0) { break; } c = 0; } else { throw new InvalidOperationException(); } } } }; if (System.Diagnostics.Debugger.IsAttached) { a(); } else { try { a(); } catch (Exception ex) { UnknownFaulted(ex); } } }; Action Receive = null; EventHandler <SocketAsyncEventArgs> Completed = (sender, e) => { if (e.SocketError != SocketError.Success) { e.Dispose(); Faulted(new SocketException((int)(e.SocketError))); return; } var Count = e.BytesTransferred; var Buffer = new Byte[Count]; Array.Copy(e.Buffer, Buffer, Count); e.Dispose(); CompletedSocket(Buffer); Buffer = null; Receive(); }; Receive = () => { if (!IsRunning) { return; } var ServerEndPoint = this.RemoteEndPoint; var ae = new SocketAsyncEventArgs(); ae.RemoteEndPoint = ServerEndPoint; ae.SetBuffer(ReadBuffer, 0, ReadBuffer.Length); ae.Completed += Completed; try { var willRaiseEvent = Socket.ReceiveFromAsync(ae); if (!willRaiseEvent) { QueueUserWorkItem(() => Completed(null, ae)); } } catch (Exception ex) { ae.Dispose(); Faulted(ex); return; } }; Receive(); }