Как (де) создавать кадры данных в WebSockets hybi 08+?

Поскольку Chrome обновлен до версии 14, они перешли от третьей версии проекта к восьмой версии проекта .

У меня есть приложение для внутреннего чата, работающее на WebSocket, и хотя я получил новое рукопожатие, структура данных, по-видимому, также изменилась. Мой сервер WebSocket основан на Nugget .

У кого-нибудь есть WebSocket, работающий с восьмой версией проекта, и есть пример того, как формировать данные, отправляемые по проводу?

(См. Также: Как отправлять и получать сообщения 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 (где maskByteindexOfByteInData 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 # отлично подходит для меня. Декодировать текстовые данные, поступающие из браузера на сервер ac # через сокет.

  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); } 

Чтобы быть более точным, Chrome перешел от версии протокола Hixie- 76 к версии протокола HyBi-10 . HyBi-08 через HyBi-10 все сообщают как версию 8, потому что это был только текст спецификации, который изменился, а не формат провода.

Кадрирование изменилось с использования ‘\ x00 … \ xff’ для использования заголовка 2-7 байтов для каждого кадра, который содержит длину полезной нагрузки между прочим. Существует диаграмма формата кадра в разделе 4.2 спецификации. Также обратите внимание, что данные с клиента (браузера) на сервер маскируются (4 байта заголовков кадров клиент-сервер содержат ключ маскирования).

Вы можете посмотреть websockify, который является WebSockets для прокси-сервера / моста TCP, который я создал для поддержки noVNC . Он реализован в python, но вы должны получить эту идею из подпрограмм encode_hybi и decode_hybi .

  • Аутентификация и авторизация Websocket весной
  • Лучший инструмент Ruby on Rails WebSocket
  • События WebSockets или Server-Sent / EventSource
  • html5 Websocket с SSL
  • Обновления в реальном времени из базы данных с использованием JSF / Java EE
  • Готовый сервер для создания WebSockets в Java?
  • Websocket vs REST при отправке данных на сервер
  • Протокол WebSockets vs HTTP
  • Доступ к HttpSession из HttpServletRequest в веб-узле @ServerEndpoint
  • Вызывает усталость HTTP / 2?
  • WSS по HTTP и WSS на HTTPS
  • Interesting Posts

    Присоединение к домашней группе Windows 7 прерывает подключения к общим ресурсам

    Строки в Java: equals vs ==

    Компьютер включается после любого режима

    Как встроить манифест приложения в приложение с помощью VS2008?

    Какой тип использует Java Collections.sort (узлы)?

    Как работают такие программы, как гитолит?

    Как преобразовать строку в IP-адрес и наоборот

    Как найти веб-браузер по умолчанию с помощью C #?

    Получение подматрицы из существующего массива

    Разрешения по умолчанию для FTP-загрузок в ubuntu (vsftpd)

    Резюме: сделайте снимок с использованием намерения камеры и отобразите фотографию с правильной ориентацией (работает, надеюсь, на все устройства)

    Ошибка при использовании Xcode 5.0 и Rcpp (средства командной строки ARE установлены)

    Как обеспечить соответствие hashCode () с equals ()?

    Основные шаги для использования MQTT в android

    Реализация карты с использованием дубликатов ключей

    Давайте будем гением компьютера.