Подтвердить что ты не робот

Передача данных через WebSocket

поскольку я использую соединения WebSocket на более регулярных базах, меня интересовало, как все работает под капотом. Таким образом, я долгое время врывался в бесконечные спецификации, но до сих пор я не мог найти ничего о том, как обманывать сам поток передачи.

Протокол WebSocket называет его фреймами данных (который описывает чистый поток данных, поэтому его также называют неконтролирующими кадрами). Насколько я понял спецификацию, нет определенной максимальной длины и не заданного значения MTU (максимальной единицы передачи), что, в свою очередь, означает, что один кадр данных WebSocket может содержать по спецификации (!) Бесконечный объем данных (пожалуйста, поправьте меня, если я ошибаюсь, я все еще участвую в этом).

После прочтения этого, я мгновенно настроил свой маленький сервер Node WebSocket. Поскольку у меня есть сильная история Ajax (также на потоковой передаче и Comet), мои ожидания были оригинальными: "Должен быть какой-то интерактивный режим для чтения данных во время его передачи". Но я неправ, не так ли?

Я начал с малого, с 4kb данных.

сервер

testSocket.emit( 'data', new Array( 4096 ).join( 'X' ) );

и, как и ожидалось, это придет на клиент как один блок данных

клиент

wsInstance.onmessage = function( data ) {
    console.log( data.length ); // 4095
};

поэтому я увеличил полезную нагрузку, и я действительно ожидал снова, что в какой-то момент обработчик на стороне клиента onmessage будет срабатывать повторно, эффектно блокируя передачу. Но, к моему шоку, этого никогда не было (node -сервер, протестированный на стороне Firefox, хром и сафари на стороне клиента). Моя самая большая полезная нагрузка была 80 МБ

testSocket.emit( 'data', new Array( 1024*1024*80 ).join( 'X' ) );

и он все еще прибыл в один большой блок данных на клиенте. Конечно, это занимает некоторое время, даже если у вас довольно хорошая связь. Вопросы здесь

  • Есть ли возможность перерезать эти потоки, похожие на режим ReadyState3 XHR?
  • существует ли ограничение по размеру для одного кадра данных ws?
  • - это веб-сайты, которые не должны передавать такие большие полезные нагрузки? (что заставило бы меня снова задаться вопросом, почему нет определенного максимального размера)

Я могу по-прежнему смотреть с неправильной точки зрения на WebSockets, возможно, необходимость отправки больших объемов данных просто не существует, и вы должны полностью или частично разбивать какие-либо данные перед отправкой?

4b9b3361

Ответ 1

Во-первых, вам необходимо провести различие между протоколом WebSocket и API WebSocket в браузерах.

Протокол WebSocket имеет ограничение размера кадра в 2 ^ 63 октета, но сообщение WebSocket может состоять из неограниченного количества кадров.

API WebSocket в браузерах не предоставляет API-интерфейс на основе фреймов или потоковой передачи, а только API на основе сообщений. Полезная нагрузка входящего сообщения всегда полностью забуферирована (в рамках реализации WebSocket браузера), прежде чем предоставлять ее JavaScript.

API других реализаций WebSocket могут предоставлять доступ к кадру, передаваемому через протокол WebSocket, на основе кадровой или потоковой передачи. Например, AutobahnPython. Вы можете прочитать больше в примерах здесь https://github.com/tavendo/AutobahnPython/tree/master/examples/twisted/websocket/streaming.

Раскрытие информации: Я являюсь оригинальным автором Autobahn и работаю в Tavendo.

Другие соображения:

Пока API-интерфейс API-интерфейса браузера JS Websocket отсутствует, вы можете получать или отправлять только полные сообщения WS.

Единственное (обычное) соединение WebSocket не может перемежать полезную нагрузку нескольких сообщений. То есть, если вы используете большие сообщения, они доставляются по порядку, и вы не сможете отправлять небольшие сообщения между ними, пока большое сообщение все еще находится на ходу.

Существует следующее расширение WebSocket (расширения - встроенный механизм для расширения протокола): мультиплексирование WebSocket. Это позволяет иметь несколько (логических) соединений WebSocket по одному базовому TCP-соединению, которое имеет несколько преимуществ.

Обратите внимание: вы можете одновременно открыть несколько WS-соединений (по различным базовым TCP-адресам) на один целевой сервер с одной JS/HTML-страницы.

Обратите также внимание: вы можете "разбить" себя на прикладном уровне: отправьте свой материал в более мелкие сообщения WS, чтобы собрать себя.

Я согласен, что в идеальном мире у вас будет API-интерфейс/Frame/Streaming в браузере и мультиплексирование WebSocket. Это даст всю силу и удобство.

Ответ 2

RFC 6455 Раздел 1.1:

Это то, что обеспечивает протокол WebSocket: [...] альтернатива HTTP-опросу для двусторонней связи с веб-страницы на удаленный сервер.

Как указано, WebSockets предназначены для связи между веб-страницей и сервером. Обратите внимание на разницу между веб-страницей и веб-браузером. Примерами являются браузерные игры и чат-приложения, которые вычитают множество небольших сообщений.

Если вы хотите отправить много MB в одном сообщении, я думаю, вы не используете WebSockets так, как они были предназначены. Если вы хотите перенести файлы, сделайте это, используя запрос Plain Old Http Request, на который отвечает Content-Disposition, чтобы браузер загрузил файл.

Итак, если вы объясните, почему вы хотите отправить такие большие объемы данных, возможно, кто-то может помочь придумать более элегантное решение, чем использовать WebSockets.

Кроме того, клиент или сервер могут отказаться от слишком больших сообщений (хотя в явном виде не указано, как это будет отклонено):

RFC 6455 Раздел 10.4:

Реализации, которые имеют реализацию и/или платформу    ограничения размера кадра или общего размера сообщения после    повторная сборка из нескольких фреймов ДОЛЖНА защитить себя от    превышая эти пределы. (Например, вредоносная конечная точка может попробовать    выдать свою равноправную память или установить атаку отказа в обслуживании    отправляя либо один большой кадр (например, размером 2 ** 60), либо отправляя    длинный поток небольших кадров, которые являются частью фрагментированного    сообщение.) Такая реализация СЛЕДУЕТ наложить ограничение на кадр    размеры и общий размер сообщения после повторной сборки из нескольких    кадров.