兄弟们,我来填坑了,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/90187478
https://download.csdn.net/download/qq_35319925/90187478 上面提供了代码链接下载地址。获取电脑本地的音频设备并实时传输音频数据到后台。这个demo是可以跑通的。方便大家使用



















