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/90187478https://download.csdn.net/download/qq_35319925/90187478 上面提供了代码链接下载地址。获取电脑本地的音频设备并实时传输音频数据到后台。这个demo是可以跑通的。方便大家使用
原文地址:https://blog.csdn.net/qq_35319925/article/details/144744970
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!