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ę?
2 odpowiedzi
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.
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.
Podobne pytania
Nowe pytania
erlang
Erlang jest językiem programowania ogólnego przeznaczenia, gromadzącym elementy bezużyteczne i środowiskiem wykonawczym, z wbudowaną obsługą współbieżności, dystrybucji i odporności na błędy.