Erlang get_tcp: длина данных recv - PullRequest
       10

Erlang get_tcp: длина данных recv

3 голосов
/ 22 февраля 2011

Я пользователь gen_tcp:recv(Socket, 0). для получения данных, но я могу получить только 1418 байт за 1 раз.Как я могу получить, сколько данных было отправлено?

1 Ответ

7 голосов
/ 22 февраля 2011

in gen_tcp:recv(Socket, 0) вы спрашиваете ядро: «Дайте мне все данные, которые доступны прямо сейчас в приемном буфере». Однако ядро ​​также может дать вам меньше. Даже для довольно быстрой ссылки вы, вероятно, нажмете медленный старт на TCP-соединении, поэтому в начале вы не получите много данных.

Решение - сделать свою собственную буферизацию. Вам придется съесть данные из нижележащего сокета, пока у вас не будет достаточно для создания сообщения. Из-за этого бинарные протоколы довольно часто реализуют свой собственный тип обмена сообщениями поверх потока.


Для записи на более длительный срок. Обычным форматом сообщения является кодирование сообщения в виде:

decode(Bin) when is_binary(Bin) ->
  <<Len:32/integer, R/binary>> = Bin,
  <<Payload:Len/binary, Remain/binary>>,
  {msg, {Len, Payload}, Remaining}.

То есть сообщения представляют собой 4 байта, представляющих 32-разрядное бигендовское целое число, за которым следует полезная нагрузка, где длина задается целым числом. Этот формат и другие подобные ему настолько распространены, что Erlang включает оптимизированные парсеры для него непосредственно в C-слое. Чтобы получить к ним доступ, вы устанавливаете опции для сокета через inet/setops/2, в нашем случае мы устанавливаем {packet, 4}. Затем мы можем получать сообщения, установив {active, once} в сокет и ждать следующего сообщения. Когда он прибудет, мы можем {active, once} снова в сокете получить следующее сообщение и так далее. В документации gen_tcp есть пример (erl -man gen_tcp, если у вас правильно установлены man-страницы Erlang).

Другими распространенными форматами являются asn.1 или даже заголовки http (!).

Tricks

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

...