void Unpack(ByteArray ba, ref int used, Action <EOpcode, byte[]> onReceiveData) { if (ba.ReadEnableSize < 2 * ByteArray.BYTE_SIZE) { //数据存在半包问题 return; } int startPos = ba.Pos; //获取第一个byte byte byte1 = ba.ReadByte(); bool fin = (byte1 & 128) == 128 ? true : false; var rsv123 = (byte1 & 112); var opcode = (EOpcode)(byte1 & 15); //获取第二个byte byte byte2 = ba.ReadByte(); bool mask = (byte2 & 128) == 128 ? true : false; var payloadLen = (byte2 & 127); int dataSize = 0; switch (payloadLen) { case 127: if (ba.ReadEnableSize < 2 * ByteArray.ULONG_SIZE) { //数据存在半包问题 return; } dataSize = (int)ba.ReadULong(); break; case 126: if (ba.ReadEnableSize < 2 * ByteArray.USHORT_SIZE) { //数据存在半包问题 return; } dataSize = ba.ReadUShort(); break; default: dataSize = payloadLen; break; } byte[] maskKeys = null; if (mask) { if (ba.ReadEnableSize < 4 * ByteArray.BYTE_SIZE) { //数据存在半包问题 return; } maskKeys = new byte[4]; for (int i = 0; i < maskKeys.Length; i++) { maskKeys[i] = ba.ReadByte(); } } switch (opcode) { case EOpcode.CONTINUE: case EOpcode.PING: case EOpcode.PONG: case EOpcode.CLOSE: //使用率低,暂不处理这种情况 onReceiveData?.Invoke(opcode, null); break; case EOpcode.TEXT: case EOpcode.BYTE: if (dataSize > 0) { if (ba.ReadEnableSize < dataSize) { //数据存在半包问题 return; } byte[] payloadData = ba.ReadBytes(dataSize); if (mask) { for (int i = 0; i < payloadData.Length; i++) { var maskKey = maskKeys[i % 4]; payloadData[i] = (byte)(payloadData[i] ^ maskKey); } } onReceiveData?.Invoke(opcode, payloadData); } break; default: Log.E(string.Format("不可识别的WS协议:{0}", opcode)); return; } used += ba.Pos - startPos; Unpack(ba, ref used, onReceiveData); }
/// <summary> /// 将要发送的数据封装为WebSocket通信数据帧。 /// 默认mask为0 /// </summary> /// <param name="data">发送的数据</param> /// <param name="isMask">是否做掩码处理(默认为false)</param> /// <param name="isFin">是否是结束帧(默认为true)</param> /// <param name="opcode">操作码(默认为TEXT)</param> byte[] CreateDataFrame(byte[] data, bool isMask = false, bool isFin = true, EOpcode opcode = EOpcode.TEXT) { int bufferSize = 10; if (null != data) { bufferSize += data.Length; } ByteArray ba = new ByteArray(bufferSize, false); int b1 = 0; if (isFin) { b1 = b1 | 128; } b1 = b1 | (int)opcode; ba.Write((byte)b1); int b2 = 0; byte[] maskKeys = null; if (isMask) { b2 = b2 | 128; maskKeys = new byte[4]; Random rand = new Random(); for (int i = 0; i < maskKeys.Length; i++) { maskKeys[i] = (byte)rand.Next(); } for (int i = 0; i < data.Length; i++) { var maskKey = maskKeys[i % 4]; data[i] = (byte)(data[i] ^ maskKey); } } if (data != null) { if (data.Length > 65535) { ba.Write((byte)(b2 | 127)); ba.Write((long)data.Length); } else if (data.Length > 125) { ba.Write((byte)(b2 | 126)); ba.Write((ushort)data.Length); } else { ba.Write((byte)(b2 | data.Length)); } if (isMask) { for (int i = 0; i < maskKeys.Length; i++) { ba.Write(maskKeys[i]); } } ba.Write(data); } else { ba.Write((byte)0); } return(ba.GetAvailableBytes()); }