pim*_*vdb 16
(另请参阅:如何在服务器端发送和接收WebSocket消息?)
这很容易,但理解格式很重要.
第一个字节几乎总是1000 0001,其中1意味着"最后一帧",三个0s是保留位,到目前为止没有任何意义,这0001意味着它是一个文本框架(Chrome随ws.send()方法发送).
(更新: Chrome现在也可以发送带有a的二进制帧ArrayBuffer.第一个字节的最后四位将是0002,因此您可以在文本和二进制数据之间进行区分.数据的解码工作方式完全相同.)
第二个字节包含a 1(意味着它被"屏蔽"(编码)),后面跟着表示帧大小的7位.如果它在000 0000和之间111 1101,那就是大小.如果是111 1110,则后面的2个字节是长度(因为它不适合7位),如果是111 1111,则后面的8个字节是长度(如果它也不适合两个字节).
接下来是四个字节,它们是解码帧数据所需的"掩码".这是使用xor编码完成的,xor编码使用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
});
Run Code Online (Sandbox Code Playgroud)
您也可以下载有用的规范(当然它包含了解格式所需的一切).
小智 12
这个c#代码对我来说很好.通过套接字解码从浏览器到ac#server的文本数据.
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);
}
Run Code Online (Sandbox Code Playgroud)