自学内容网 自学内容网

TCP客户端模拟链接websocket服务端发送消息(二)

兄弟们,我来填坑了,o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o,前几天写了个tcp模拟websocket客户端的以为完成,后面需要发送消息给服务端,以为简单不就是一个发送消息么,这不是一下的事情,诺 sslStrem.Write(bt,0,bt.length);这不就是么,结果结果啪啪啪打脸,脸都要肿了o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o。

错误信息:“xeaThe client frame was not masked but all client frames must be masked” 后面查找资料发现需要按照websocket协议来发送websocket结构体的消息帧。

如下图

WebSocket 消息帧结构

    FIN(1位): 表示是否是最后一帧。
    RSV1, RSV2, RSV3(各1位): 保留位,通常为 0。
    Opcode(4位): 帧的类型(例如:文本帧、二进制帧、关闭帧等)。
    Mask(1位): 表示负载是否被掩码。
    Payload length(7/7+16/7+64位): 表示负载数据的长度。
    Masking key(32位): 如果 Mask 为 1,则存在掩码键。
    Payload data: 实际传输的数据。

找了一大堆资料结果还是没成功,一想到有开源的websocket开源代码里面肯定是有发送消息的方法。得按照这个思路在websocket-sharp开源里找到了,然后在里面看啊看游啊游,头都要大了,最后还是仿写了一套相对简单的,后面一试成功了不容易啊。

代码如下:

   public void Send2(string data)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(data);
            Stream sourceStream = new MemoryStream(bytes);
            try
            {
                var len = sourceStream.Length;

                if (len == 0)
                {
                    bool sent3 = send2(0x1, 0x1, new byte[0], false);
                    return;
                }

                var quo = len / 1016;
                var rem = (int)(len % 1016);
                byte[] buff = null;

                if (quo == 0)
                {
                    buff = new byte[rem];

                    bool sent2 = sourceStream.Read(buff, 0, rem) == rem && send2(0x1, 0x1, buff, false);
                    return;
                }

                if (quo == 1 && rem == 0)
                {
                    buff = new byte[1016];
                    bool sent2 = sourceStream.Read(buff, 0, 1016) == 1016 && send2(0x1, 0x1, buff, false);
                    return;
                }

                /* Send fragments */

                // Begin

                buff = new byte[1016];

                var sent = sourceStream.Read(buff, 0, 1016) == 1016 && send2(0x0, 0x1, buff, false);

                if (!sent)
                    return;

                // Continue

                var n = rem == 0 ? quo - 2 : quo - 1;

                for (long i = 0; i < n; i++)
                {
                    sent = sourceStream.Read(buff, 0, 1016) == 1016 && send2(0x0, 0x0, buff, false);

                    if (!sent)
                        return;
                }

                // End

                if (rem == 0)
                    rem = 1016;
                else
                    buff = new byte[rem];

                sent = sourceStream.Read(buff, 0, rem) == rem && send2(0x1, 0x0, buff, false);
                return;

            }
            catch
            {
            }
            finally
            {
                sourceStream.Dispose();
            }
        }

        private bool send2(byte fin, byte opcode, byte[] data, bool compressed)
        {
            byte _payloadLength;

            byte _rsv1;
            byte _rsv2;
            byte _rsv3;
            byte[] _extPayloadLength;
            byte[] _maskingKey;
            byte _mask;
            //PayloadData _payloadData = new PayloadData(data);


            _rsv1 = compressed ? (byte)0x1 : (byte)0x0;
            _rsv2 = 0x0;
            _rsv3 = 0x0;
            var len = data.Length;


            if (len < 126)
            {
                _payloadLength = (byte)len;
                _extPayloadLength = new byte[0];
            }
            else if (len < 0x010000)
            {
                _payloadLength = (byte)126;
                var ret = BitConverter.GetBytes((ushort)len);
                Array.Reverse(ret);
                _extPayloadLength = ret;
                //_extPayloadLength = ((ushort)len).ToByteArray(ByteOrder.Big);

            }
            else
            {
                _payloadLength = (byte)127;
                var ret = BitConverter.GetBytes((ulong)len);
                Array.Reverse(ret);
                _extPayloadLength = ret;
                //_extPayloadLength = ((ulong)len).ToByteArray(ByteOrder.Big);
            }

            if (true)
            {
                _mask = 0x1;
                var key = new byte[4];
                RNGCryptoServiceProvider RandomNumber = new RNGCryptoServiceProvider();
                RandomNumber.GetBytes(key);
                _maskingKey = key;


                for (long i = 0; i < data.Length; i++)
                {
                    data[i] = (byte)(data[i] ^ key[i % 4]);
                }

            }
            using (var buff = new MemoryStream())
            {
                var header = (int)fin;
                header = (header << 1) + (int)_rsv1;
                header = (header << 1) + (int)_rsv2;
                header = (header << 1) + (int)_rsv3;
                header = (header << 4) + (int)opcode;
                header = (header << 1) + (int)_mask;
                header = (header << 7) + (int)_payloadLength;

                var uint16Header = (ushort)header;
                var ret = BitConverter.GetBytes(uint16Header);
                Array.Reverse(ret);
                var rawHeader = ret;

                buff.Write(rawHeader, 0, 2);

                if (_payloadLength >= 126)
                    buff.Write(_extPayloadLength, 0, _extPayloadLength.Length);

                if (_mask == 0x1)
                    buff.Write(_maskingKey, 0, 4);

                if (_payloadLength > 0)
                {
                    var bytes = data;

                    if (_payloadLength > 126)
                    {
                        using (var src = new MemoryStream(bytes))
                            src.CopyTo(buff, 1024);
                    }
                    else
                        buff.Write(bytes, 0, bytes.Length);
                }

                buff.Close();

                var rawFrame = buff.ToArray();
                try
                {
                    sslStream.Write(rawFrame, 0, rawFrame.Length);
                }
                catch
                {
                    return false;
                }
                return true;
            }

        }

https://download.csdn.net/download/qq_35319925/90187478icon-default.png?t=O83Ahttps://download.csdn.net/download/qq_35319925/90187478 上面提供了代码链接下载地址。获取电脑本地的音频设备并实时传输音频数据到后台。这个demo是可以跑通的。方便大家使用


原文地址:https://blog.csdn.net/qq_35319925/article/details/144744970

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!