(另请参见:如何在服务器端发送和接收WebSocket消息?)
这很容易,但重要的是要了解格式。
第一个字节几乎总是1000 0001
,其中1
表示“最后一帧”,三个0
是暂时没有任何意义的保留位,0001
表示它是文本帧(Chrome使用ws.send()
方法发送)。
(更新: Chrome现在也可以使用ArrayBuffer
发送二进制帧。第一个字节的最后四位将为0002
,因此您可以区分文本和二进制数据。数据的解码方式完全相同。)
第二个字节包含一个1
(表示它被“屏蔽”(编码)),后面是七个位数,表示帧大小。如果它在000 0000
和111 1101
之间,那就是大小。如果是111 1110
,则下面2个字节是长度(因为它不适合7位),如果是111 1111
,则下面8个字节是长度(如果它也不适合两个字节)。
随后是四个字节,它们是“掩码”,你需要用它们解码帧数据。这是使用异或编码进行的,该编码使用数据的indexOfByteInData mod 4
中定义的掩码之一。解码的方法很简单,就像encodedByte xor maskByte
一样(其中maskByte
是indexOfByteInData mod 4
)。
现在我必须说我对C#一窍不通,但这是伪代码(有点JavaScript口音,恐怕):
var length_code = bytes[1] & 127, // remove the first 1 by doing '& 127'
masks,
data;
if(length_code === 126) {
masks = bytes.slice(4, 8); // 'slice' returns part of the byte array
data = bytes.slice(8); // and accepts 'start' (inclusively)
} else if(length_code === 127) { // and 'end' (exclusively) as arguments
masks = bytes.slice(10, 14); // Passing no 'end' makes 'end' the length
data = bytes.slice(14); // of the array
} else {
masks = bytes.slice(2, 6);
data = bytes.slice(6);
}
// 'map' replaces each element in the array as per a specified function
// (each element will be replaced with what is returned by the function)
// The passed function accepts the value and index of the element as its
// arguments
var decoded = data.map(function(byte, index) { // index === 0 for the first byte
return byte ^ masks[ index % 4 ]; // of 'data', not of 'bytes'
// xor mod
});
您还可以下载规范,这可能会很有帮助(因为它当然包含了您需要理解格式的一切内容)。
这段C#代码对我来说运行良好。通过套接字将来自浏览器的文本数据解码到C#服务器。
public static string GetDecodedData(byte[] buffer, int length)
{
byte b = buffer[1];
int dataLength = 0;
int totalLength = 0;
int keyIndex = 0;
if (b - 128 <= 125)
{
dataLength = b - 128;
keyIndex = 2;
totalLength = dataLength + 6;
}
if (b - 128 == 126)
{
dataLength = BitConverter.ToInt16(new byte[] { buffer[3], buffer[2] }, 0);
keyIndex = 4;
totalLength = dataLength + 8;
}
if (b - 128 == 127)
{
dataLength = (int)BitConverter.ToInt64(new byte[] { buffer[9], buffer[8], buffer[7], buffer[6], buffer[5], buffer[4], buffer[3], buffer[2] }, 0);
keyIndex = 10;
totalLength = dataLength + 14;
}
if (totalLength > length)
throw new Exception("The buffer length is small than the data length");
byte[] key = new byte[] { buffer[keyIndex], buffer[keyIndex + 1], buffer[keyIndex + 2], buffer[keyIndex + 3] };
int dataIndex = keyIndex + 4;
int count = 0;
for (int i = dataIndex; i < totalLength; i++)
{
buffer[i] = (byte)(buffer[i] ^ key[count % 4]);
count++;
}
return Encoding.ASCII.GetString(buffer, dataIndex, dataLength);
}
totalLength
是什么,为什么要将keyIndex + 4
加到它上面? - David Gölzhäuser