示例#1
0
        /// <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();
        }