Да (или Нет, подробности см. В комментариях).
Рассмотрим:
Оболочка 1:
1> {ok, L} = gen_tcp:listen(8080, [binary, {packet, 0}, {active, false}]).
{ok,#Port<0.506>}
2> {ok, C} = gen_tcp:accept(L). %% Blocks
...
Оболочка 2:
1> {ok, S} = gen_tcp:connect("localhost", 8080, [binary, {packet, 0}]).
{ok,#Port<0.516>}
2> gen_tcp:send(S, <<0,2,72,105>>).
ok
3>
Оболочка 1, продолжение:
...
{ok,#Port<0.512>}
3> {ok, <<Len:16/integer>>} = gen_tcp:recv(C, 2).
{ok,<<0,2>>}
4> Len.
2
5> {ok, Data} = gen_tcp:recv(C, Len).
{ok,<<"Hi">>}
6>
Однако это полезно, если вы хотите только подтвердить поведение.В действительности вы должны изменить параметр {packet, N}
, чтобы определить, сколько байтов должно быть длиной пакета (в системах с прямым порядком байтов).
То же, что и раньше, но без извлечения длины явно (обратите внимание, длина пакета = 2 вshell 1):
Shell 1:
1> {ok, L} = gen_tcp:listen(8080, [binary, {packet, 2}, {active, false}]).
{ok,#Port<0.506>}
2> {ok, C} = gen_tcp:accept(L). %% Blocks
...
В этом случае Эрланг удалит первые 2 байта, а recv/2
заблокирует до тех пор, пока ему не потребуется столько байтов.В этом случае длина чтения должна быть 0 в recv/2
.
Оболочка 2:
1> {ok, S} = gen_tcp:connect("localhost", 8080, [binary, {packet, 0}]).
{ok,#Port<0.516>}
2> gen_tcp:send(S, <<0,2,72,105>>).
ok
3>
Оболочка 1:
...
{ok,#Port<0.512>}
3> {ok, Data} = gen_tcp:recv(C, 0).
{ok,<<"Hi">>}
В этом случае я не указываю параметр {packet, N}
в оболочке 2 просто для демонстрации идеи, но обычно это не 0. Если установлена опция packet
, то gen_tcp
автоматически добавит / удалит столько байтов изpackage.
Если вы укажете пакет 0, тогда вы должны сделать recv/2
с длиной> = 0, и поведение будет таким же, как в C. Вы можете смоделировать неблокирующие приемы, дав короткий тайм-аутпри выполнении приема, и это вернет {error, timeout} в этом случае.
Подробнее об этом можно прочитать здесь: http://www.erlang.org/doc/man/gen_tcp.html http://www.erlang.org/doc/man/inet.html#setopts-2
Надеюсь, это все прояснит.