erlang: как получать сообщения HTTP / RTSP из сокета? - PullRequest
2 голосов
/ 05 апреля 2019

Я хочу управлять сеансами HTTP или RTSP с помощью Erlang.

Например, стандартный сеанс для протокола RTSP выглядит следующим образом:

OPTIONS rtsp://192.168.1.55/test/ RTSP/1.0\r\n
CSeq: 1\r\n
User-Agent: VLC media player (LIVE555 Streaming Media v2008.07.24)\r\n
...
PLAY rtsp://192.168.1.55/test/ RTSP/1.0\r\n
CSeq: 5\r\n
Session: 1\r\n
Range: npt=0.000-\r\n
User-Agent: VLC media player (LIVE555 Streaming Media v2008.07.24)\r\n

Длина каждого сообщения разная. Для erlang gen_server:listen использует опцию {active, true} (для получения неограниченного количества данных) или {active, false} (для получения фиксированной длины данных).

Есть ли рекомендуемый способ получения и анализа таких сообщений переменной длины?

1 Ответ

4 голосов
/ 06 апреля 2019

Для HTTP используйте один из режимов пакетов HTTP, задокументированных для функции inet:setopts/2.Например, чтобы установить сокет для получения HTTP-сообщений в виде двоичных файлов, вы можете установить {packet, http_bin} для сокета.Взгляните на мой простой пример веб-сервера , чтобы узнать, как использовать режимы HTTP-пакетов.

Для RTSP нет встроенного синтаксического анализатора пакетов, но поскольку заголовки RTSP ориентированы на строкиКак и HTTP, вы можете выполнять собственный анализ заголовка в режиме {packet, line}.В этом режиме вы будете получать по одному заголовку за раз, пока не получите пустую строку, указывающую конец заголовков.Затем вы можете переключить сокет в режим {packet, raw}, чтобы получить любое тело сообщения.Заголовок Content-Length, если присутствует, указывает размер любого тела сообщения.

Упомянутые вами режимы сокетов {active, true} vs {active, false} определяют, как данные поступают в управляющий процесс (владелец) сокета.

  • Режим {active, true} отправляет все данные из сокета в управляющий процесс, как только они поступают.В этом режиме данные поступают в виде сообщений в очередь сообщений владельца.Получение сообщений в очереди сообщений процесса - это здорово, поскольку оно позволяет процессу обрабатывать и другие сообщения Erlang, не связанные с сокетами, при обработке данных сокетов, но {active, true} используется не так часто, поскольку не оказывает обратного давления TCP наотправитель, и поэтому быстрый отправитель может переполнить получателя.
  • В режиме {active, false} требуется, чтобы получатель вызвал gen_tcp:recv/2,3 в сокете для извлечения данных.Это не имеет проблемы противодавления {active, true}, но может сделать обработку сообщений неудобной, поскольку процесс Erlang должен активно запрашивать данные сокета, а не просто сидеть в цикле receive, как это может быть с другим active mode.
  • Два других active режима, которые вы не упомянули, это {active, once} и {active, N}.В режиме {active, once} принимающий процесс получает одно сообщение через свою очередь сообщений за раз, причем сокет переходит в пассивный режим {active, false} после каждого сообщения.Чтобы получить другое сообщение, получатель должен снова установить {active, once} на сокете, когда он будет готов к следующему сообщению.Этот режим хорош тем, что сообщения поступают в очередь сообщений процесса точно так же, как и в режиме {active, true}, но обратное давление по-прежнему работает.Режим {active, N} аналогичен, за исключением того, что сообщения N, а не только одно, принимаются до того, как сокет возвращается в пассивный режим.
...