コード例 #1
0
ファイル: WebSocket.cs プロジェクト: Jaofeng/Library
        /// <summary>
        /// 當完成接收資料時,將呼叫此函示
        /// 如果客戶端關閉連接,將會一併關閉此連線(Socket)
        /// 如果收到數據接著將數據返回到客戶端
        /// </summary>
        /// <param name="e">已完成接收的 SocketAsyncEventArg 物件</param>
        protected override void ProcessReceive(SocketAsyncEventArgs e)
        {
            int            index = Thread.CurrentThread.ManagedThreadId;
            AsyncUserToken token = e.UserToken as AsyncUserToken;

            if (token == null || token.IsDisposed || m_IsShutdown || m_IsDisposed)
            {
                return;
            }
            IntPtr          origHandle      = IntPtr.Zero;
            Socket          s               = token.Client;
            WebSocketClient ac              = null;
            EndPoint        remote          = null;
            IPEndPoint      remote4Callback = null;
            string          rep             = "Unknow";

            if (e.RemoteEndPoint != null)
            {
                rep = e.RemoteEndPoint.ToString();
            }
            try
            {
                origHandle = new IntPtr(s.Handle.ToInt32());
                remote     = s.RemoteEndPoint;
                IPEndPoint ipp = (IPEndPoint)remote;
                remote4Callback = new IPEndPoint(ipp.Address, ipp.Port);
            }
            catch (ObjectDisposedException) { }
            try
            {
                if (e.BytesTransferred > 0)
                {
                    if (e.SocketError == SocketError.Success)
                    {
                        ac = (WebSocketClient)m_Clients[s.RemoteEndPoint.ToString()];
                        int         count = e.BytesTransferred;
                        List <byte> rec   = new List <byte>();
                        if ((token.CurrentIndex + count) > token.BufferSize)
                        {
                            rec.AddRange(token.ReceivedData);
                            token.ClearBuffer();
                        }
                        token.SetData(e);
                        if (s.Available == 0)
                        {
                            rec.AddRange(token.ReceivedData);
                            token.ClearBuffer();
                        }

                        if (ac == null)
                        {
                            Debug.Print("Unknow Socket Connect!!");
                            this.CloseClientSocket(e);
                            return;
                        }

                        if (ac != null)
                        {
                            Interlocked.Add(ref ac.m_ReceiveByteCount, count);
                        }
                        if (!m_IsShutdown && !m_IsDisposed)
                        {
                            m_Counters[ServerCounterType.TotalReceivedBytes]?.IncrementBy(count);
                            m_Counters[ServerCounterType.RateOfReceivedBytes]?.IncrementBy(count);
                        }

                        #region 解析封包內容
                        byte[] data = rec.ToArray();
                        if (!((data[0] & 0x80) == 0x80))
                        {
                            Debug.Print("Exceed 1 Frame. Not Handle");
                            return;
                        }
                        // 是否包含Mask(第一個bit為1代表有Mask),沒有Mask則不處理
                        if (!((data[1] & 0x80) == 0x80))
                        {
                            Debug.Print("Exception: No Mask");
                            this.CloseClientSocket(e);
                            return;
                        }
                        // 資料長度 = dataBuffer[1] - 127
                        int    payloadLen  = data[1] & 0x7F;
                        byte[] masks       = new byte[4];
                        byte[] payloadData = null;
                        switch (payloadLen)
                        {
                        case 126:
                            #region 包含16 bit Extend Payload Length
                        {
                            Array.Copy(data, 4, masks, 0, 4);
                            payloadLen  = (UInt16)(data[2] << 8 | data[3]);
                            payloadData = new Byte[payloadLen];
                            Array.Copy(data, 8, payloadData, 0, payloadLen);
                            break;
                        }

                            #endregion
                        case 127:
                            #region 包含 64 bit Extend Payload Length
                        {
                            Array.Copy(data, 10, masks, 0, 4);
                            var uInt64Bytes = new Byte[8];
                            for (int i = 0; i < 8; i++)
                            {
                                uInt64Bytes[i] = data[9 - i];
                            }
                            UInt64 len = BitConverter.ToUInt64(uInt64Bytes, 0);

                            payloadData = new Byte[len];
                            for (UInt64 i = 0; i < len; i++)
                            {
                                payloadData[i] = data[i + 14];
                            }
                            break;
                        }

                            #endregion
                        default:
                            #region 沒有 Extend Payload Length
                        {
                            Array.Copy(data, 2, masks, 0, 4);
                            payloadData = new Byte[payloadLen];
                            Array.Copy(data, 6, payloadData, 0, payloadLen);
                            break;
                        }
                            #endregion
                        }
                        // 使用 WebSocket Protocol 中的公式解析資料
                        for (var i = 0; i < payloadLen; i++)
                        {
                            payloadData[i] = (Byte)(payloadData[i] ^ masks[i % 4]);
                        }

                        // 解析出的資料
                        Debug.Print("Data:{0}", payloadData.ToHexString());
                        #endregion

                        base.OnDataReceived(ac, payloadData);

                        if (!ac.IsConnected)
                        {
                            RecyclingSocket(origHandle, remote4Callback, e);
                            return;
                        }
                        try
                        {
                            if (s != null && !s.ReceiveAsync(e))                                // 讀取下一個由客戶端傳送的封包
                            {
                                this.ProcessReceive(e);
                            }
                        }
                        catch (ObjectDisposedException) { }
                        catch (Exception ex)
                        {
                            if (!m_IsShutdown && !m_IsDisposed)
                            {
                                Debug.Print(ex.Message);
                            }
                        }
                    }
                    else
                    {
                        base.ProcessError(e);
                    }
                }
                else
                {
                    RecyclingSocket(origHandle, remote4Callback, e);
                }
            }
            catch (KeyNotFoundException)
            {
                this.CloseClientSocket(e);
            }
            catch (ObjectDisposedException) { }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
                this.CloseClientSocket(e);
            }
        }