我正在编写一个c#web套接字实现,每当我发送大于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但<=65536字节,我需要写3个字节——第一个字节是126;下面的2个字节给出了消息长度。对于大于65536字节的消息,我需要写入9个字节——第一个字节是127;下面的8个字节给出了消息长度。
正如你所看到的,我在上面的代码中完成了所有这些,但消息无法发送。
看起来这里面有一个bug:
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);
这是因为即使Int32
只有4个字节长,您也试图将32位数字移位到8个字节。最终结果是,您在8个字节中两次存储相同的32位数字。您可以将length
转换为ulong
,然后使用该值,您的代码应该可以工作。否则
我更喜欢用别人的代码来做像比特移位这样无聊的事情。
这种比特转换代码(及其错误)已经传播得很广(你不是第一个看到这个问题的人)。
如果你从nuget中获得Jon Skeet的MiscUtil,你会用以下代码获得更好的结果(额外的好处是它更容易阅读):
frame[1] = (byte)127;
EndianBitConverter.Big.CopyBytes((ulong)length, frame, 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);
我测试了这个代码,运行良好!