Czy mogę zagnieździć połączenia receive {tcp, Socket, Bin} ->? Na przykład mam pętlę najwyższego poziomu o nazwie Loop, która po otrzymaniu danych tcp wywołuje funkcję parse_header, która parsuje dane nagłówka (liczba całkowita, która wskazuje rodzaj danych do śledzenia, a tym samym ich rozmiar), po czym muszę otrzymać cały ładunek przed przejściem dalej.

Mogę otrzymać tylko 4 bajty, gdy potrzebuję pełnych 20 bajtów i chciałbym wywołać odbiór w oddzielnej funkcji o nazwie parse_payload. Tak więc łańcuch wywołań będzie wyglądał jak loop->parse_header->parse_payload i chciałbym, aby parse_payload wywołał
receive {tcp, Socket, Bin} ->.

Nie wiem, czy wszystko jest w porządku, czy też całkowicie coś zepsuję i mogę to zrobić tylko w funkcji Loop. Czy ktoś może mnie oświecić? Jeśli wolno mi to zrobić, czy naruszam jakąś najlepszą praktykę?

0
Xavier 18 luty 2012, 05:52

2 odpowiedzi

Najlepsza odpowiedź

Może możesz sprawdzić przykładowy kod dla "programowania erlang". Strona pobierania to Kod źródłowy programowania Erlang

W pliku socket_examples.erl sprawdź funkcję „receive_data”.

W przypadku wiadomości perse, myślę, że powinieneś określić, jak oddzielić wiadomości jeden po drugim (o stałej długości lub z bajtem zakończenia), a następnie przeanalizować nagłówek wiadomości i ładunek.

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.
2
Muzaaya Joshua 18 luty 2012, 11:54

Możesz także ustawić gniazdo gen_tcp w trybie pasywnym. W ten sposób proces będący właścicielem nie otrzyma danych wejściowych przez komunikaty, ale musi je pobrać za pomocą gen_tcp:recv(Socket, ByteCount), które zwraca albo {ok, Input} lub {błąd, powód}. Ponieważ ta metoda czeka w nieskończoność na bajty, możesz chcieć dodać limit czasu za pomocą gen_tcp:recv/3. (Dokumentacja Erlanga gen_tcp:recv)

Chociaż na pierwszy rzut oka może się wydawać, że proces nie jest teraz w stanie całkowicie zareagować na wysłane do niego wiadomości, istnieje następujące obejście, które nieco poprawia sytuację:

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.

Jeśli nie dodasz tutaj limitu czasu do gen_tcp:recv, inne procesy mogą czekać całe wieki, aż f1 obsłuży ich komunikaty.

1
clonejo 19 luty 2012, 14:52