Websocket 以大消息关闭
Posted
技术标签:
【中文标题】Websocket 以大消息关闭【英文标题】:Websocket closes with large messages 【发布时间】:2015-12-02 01:34:08 【问题描述】:我正在编写一个 c# web socket 实现,并且每当我发送大于 65535 字节的消息时;客户端(javascript)无法加载消息并关闭连接。 (之前说的是无效帧,现在什么都没有了)
我正在像这样对消息进行编码
public static Byte[] EncodeMessageToSend(String message)
Byte[] response;
Byte[] bytesRaw = Encoding.UTF8.GetBytes(message);
Byte[] frame = new Byte[10];
Int32 indexStartRawData = -1;
Int32 length = bytesRaw.Length;
frame[0] = (Byte)129;
if (length <= 125)
frame[1] = (Byte)length;
indexStartRawData = 2;
else if (length >= 126 && length <= 65535)
frame[1] = (Byte)126;
frame[2] = (Byte)((length >> 8) & 255);
frame[3] = (Byte)(length & 255);
indexStartRawData = 4;
else
frame[1] = (Byte)127;
frame[2] = (Byte)((length >> 56) & 255);
frame[3] = (Byte)((length >> 48) & 255);
frame[4] = (Byte)((length >> 40) & 255);
frame[5] = (Byte)((length >> 32) & 255);
frame[6] = (Byte)((length >> 24) & 255);
frame[7] = (Byte)((length >> 16) & 255);
frame[8] = (Byte)((length >> 8) & 255);
frame[9] = (Byte)(length & 255);
indexStartRawData = 10;
response = new Byte[indexStartRawData + length];
Int32 i, reponseIdx = 0;
//Add the frame bytes to the reponse
for (i = 0; i < indexStartRawData; i++)
response[reponseIdx] = frame[i];
reponseIdx++;
//Add the data bytes to the response
for (i = 0; i < length; i++)
response[reponseIdx] = bytesRaw[i];
reponseIdx++;
return response;
65535 字节以下的消息可以正常发送。任何帮助表示赞赏。
澄清我试图发送的消息是 120283 字节;错误代码为 1006
对于最多 125 个字节的消息,代码是正确的。 对于消息 > 125 但
如您所见,我在上面的代码中完成了所有这些操作,但消息发送失败。
【问题讨论】:
您看起来会从 miscutil (nuget) 中 Jon Skeet 的 EndianBitConverter 中受益,这将使您的代码更易于阅读。 【参考方案1】:这似乎有一个错误:
frame[1] = (Byte)127;
frame[2] = (Byte)((length >> 56) & 255);
frame[3] = (Byte)((length >> 48) & 255);
frame[4] = (Byte)((length >> 40) & 255);
frame[5] = (Byte)((length >> 32) & 255);
frame[6] = (Byte)((length >> 24) & 255);
frame[7] = (Byte)((length >> 16) & 255);
frame[8] = (Byte)((length >> 8) & 255);
frame[9] = (Byte)(length & 255);
这是因为您试图将 32 位数字移位超过 8 个字节,即使 Int32
只有 4 个字节长。最终结果是,您最终在 8 个字节上存储了两次相同的 32 位数字。您可以将 length
转换为 ulong
并改用该值,您的代码应该可以工作。否则……
我更喜欢用别人的代码来做一些无聊的事情,比如位移。
这个位移代码(及其错误)已经传播得非常广泛(你不是第一个看到这个问题的人)。
如果您从 nuget 获取 Jon Skeet 的 MiscUtil,您将使用以下代码获得更好的结果(另外,它更易于阅读):
frame[1] = (byte)127;
EndianBitConverter.Big.CopyBytes((ulong)length, frame, 2);
【讨论】:
很棒,已修复。我自己并不喜欢原始代码,所以这是一个受欢迎的变化。【参考方案2】:错误在于发送一个长变量,但长度是 Int32。 有几种方法可以解决,例如:
frame[1] = (Byte)127;
frame[2] = 0;
frame[3] = 0;
frame[4] = 0;
frame[5] = 0;
frame[6] = (Byte)((length >> 24) & 255);
frame[7] = (Byte)((length >> 16) & 255);
frame[8] = (Byte)((length >> 8) & 255);
frame[9] = (Byte)(length & 255);
我测试了这段代码并且工作正常!
【讨论】:
以上是关于Websocket 以大消息关闭的主要内容,如果未能解决你的问题,请参考以下文章