Должен ли я делать вложенные приемы для данных TCP? - PullRequest
0 голосов
/ 18 февраля 2012

Могу ли я вложить receive {tcp, Socket, Bin} -> звонки? Например, у меня есть цикл верхнего уровня, называемый Loop, который после получения данных tcp вызывает функцию parse_header для анализа данных заголовка (целое число, которое указывает на тип данных, которым следует следовать и, следовательно, их размер), после этого мне нужно получить вся полезная нагрузка, прежде чем двигаться дальше.

Я мог бы получить только 4 байта, когда мне нужны полные 20 байтов, и я хотел бы вызвать receive в отдельной функции parse_payload. Таким образом, цепочка вызовов будет выглядеть как loop->parse_header->parse_payload, и я бы хотел, чтобы parse_payload вызывал
receive {tcp, Socket, Bin} ->.

Я не знаю, нормально ли это или я собираюсь все испортить и могу делать это только в функции Loop. Может ли кто-нибудь просветить меня? Если мне разрешено это делать, я нарушаю какую-то передовую практику?

Ответы [ 2 ]

2 голосов
/ 18 февраля 2012

Может быть, вы можете проверить пример кода для "Erlang программирования". Страница загрузки: Исходный код программирования Erlang

В файле socket_examples.erl, пожалуйста, проверьте функцию «receive_data».

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

receive_data(Socket, SoFar) ->
    receive
    {tcp,Socket,Bin} ->    %% (3)
        receive_data(Socket, [Bin|SoFar]);
    {tcp_closed,Socket} -> %% (4)
        list_to_binary(reverse(SoFar)) %% (5)
    end.
1 голос
/ 19 февраля 2012

Вы также можете установить гнездо gen_tcp в пассивном режиме. Таким образом, процесс-владелец не получит входные данные сообщениями, но должен извлечь их, используя gen_tcp: recv (Socket, ByteCount) , который возвращает либо {ok, Input} или {ошибка, причина} . Поскольку этот метод бесконечно ждет байтов, вы можете добавить время ожидания, используя gen_tcp: recv / 3 . ( Erlang документация gen_tcp: recv )

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

f1(X) ->
    receive
        message1 ->
            ... do something ...,
            f1(X);
        message2 ->
            ... do something ...,
            f1(X)
        after 0 %timeout in ms
            {ok, Input} = gen_tcp:recv(Socket, ByteCount, Timeout),
            ... do something ... % maybe call some times gen_tcp:recv again
            f1(X)
    end.

Если вы не добавите тайм-аут в gen_tcp: recv здесь, другие процессы могут ждать целую вечность, пока f1 обработает их сообщения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...