/// <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); } }