Ответ 1
(См. также: Как отправлять и получать сообщения WebSocket на стороне сервера?)
Это довольно легко, но важно понимать формат.
Первый байт почти всегда 1000 0001
, где 1
означает "последний кадр", три 0
являются зарезервированными битами без какого-либо значения, а 0001
означает, что это текстовый фрейм (который Chrome отправляет с помощью метода ws.send()
).
( Обновление: Теперь Chrome может также отправлять двоичные кадры с помощью ArrayBuffer
. Последние четыре бита первого байта будут 0002
, поэтому вы можете различать текст и двоичные данные. Декодирование данных работает точно так же.)
Второй байт содержит 1
(это означает, что он "замаскирован" (закодирован)), за которым следуют семь бит, которые представляют размер кадра. Если это между 000 0000
и 111 1101
, то размер. Если он 111 1110
, следующие 2 байта - это длина (потому что он не помещается в семь бит), а если он 111 1111
, следующие 8 байтов - это длина (если он не будет вписываться в два байта либо).
Ниже приведены четыре байта, которые являются "масками", которые необходимо декодировать данные кадра. Это делается с использованием xor-кодирования, которое использует одну из масок, как определено indexOfByteInData mod 4
данных. Декодирование просто работает как encodedByte xor maskByte
(где maskByte
есть indexOfByteInData mod 4
).
Теперь я должен сказать, что у меня вообще нет опыта с С#, но это какой-то псевдокод (какой-то 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
});
Вы также можете скачать спецификацию, которая может быть полезной (она, конечно, содержит все необходимое для понимания формата).