예제 #1
0
        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);
        }
예제 #2
0
        /// <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());
        }