Erlang. Параметры TCP/IP сокета
Небольшая шпаргалка по параметрам TCP/IP сокетов в Erlang по-русски. Все взято от сюда:1) erlang.org/doc/man/gen_tcp.html2) www.erlang.org/doc/man/inet.html#setopts-23) learnyousomeerlang.com/buckets-of-sockets#tcp-and-udp-brotocolsСразу пример:
… -define (TCP_OPTIONS, [binary, {packet, raw}, {active, false}]). … {ok, Socket} = gen_tcp: listen (Port, ? TCP_OPTIONS), … Параметры сокета задаются в массиве (листе) через запятую. Порядок и количество параметров определяется по вкусу.Режим, определяющий тип данных (mode) Выбирая режим, мы решаем, как VM Erlang будет давать нам информацию из сокета: — binary — в виде двоичных данных; — list — в виде спискаСчитается, что с двоичными данными Erlang работает быстрее, чем со списками.ПримерСокет принял данные из трех байт: 01 02 03
%% в двоичном виде
Msg = <<1,2,3>>, %% допустим, данные поместили в переменную Msg
%% парсим
<
%% в виде списка (list) Msg = [1,2,3], %% данные %% парсим [FirstByte|Tail] = Msg, %% берем первый элемент и остаток сообщения %% итог: %% в Msg будет 1 %% в Tail будет [2,3] Режим чтения данных из сокета (active) Этим параметром задается режим и способ чтения данных из сокета.В режиме {active, false} сокет работает в так называемом passive mode. Рекомендуется применять при больших объемах данных и высоких скоростях; в случаях, когда разная скорость работы сети у клиента и сервера; чтобы клиент не завалил сообщениями сервер. А все потому, что в этом режиме используется tcp/ip flow control (открытие для меня).
Данные читаются непосредственно из сокета
recv (Socket) → case gen_tcp: recv (Socket, 0) of {ok, RcvdData} → %% RcvdData — считанные данные recv (Sock); {error, closed} → %% закрылся {error, closed} end. В режиме {active, true} данные, принятые из сокета отправляются процессу в виде сообщений. Но flow control тут нет, поэтому можно закидать принимающую сторону большим объемом данных.Данные из сокета передаются процессу в виде сообщений
recv (Socket) → receive {tcp, Socket, RcvdData} → %% RcvdData — считанные данные recv (Sock); {tcp_closed, Socket} → {error, closed} end. В принципе, в этом случае процесс тоже будет висеть на receive, пока не будут приняты сообщения. Но в этом случае можно обрабатывать сообщения с данными не только от сокета, но и от других процессов (например, сообщение с данными, которые нужно отправить в сокет).Параметры сокета можно менять на ходу
inet: setopts (Socket, [{active, once}]), В режиме {active, once} сокет работает в активном режиме до приема первого сообщения. После этого он переходит в пассивный режим с управлением потоком (tcp flow control). Это как раз тот случай, когда мы хотим получать данные сокета в виде сообщений и в то же время нам нужен flow control. Каждый раз, когда мы хотим принимать данные, нам нужно менять свойство active у сокета. recv (Socket) → inet: setopts (Socket, [{active, once}]), receive {tcp, Socket, RcvdData} → %% RcvdData — считанные данные recv (Sock); {tcp_closed, Socket} → {error, closed} end. Кроме once можно задать число. Подробнее можно прочесть в документации
packet Вариантов значений этого параметра может быть много. Опишу только самые интересные и те, которые некоторые ребята понимают не так.Данные из сокета могут приниматься как бессмысленным потоком, так и в виде определенных пакетов.
В режиме {packet,0} или {packet, raw} данные никак не пакуются и передаются на обработку как есть.
В режиме {packet,1×2 | 4} перед данными идет 1, 2 или 4 байта, которые задают длину сообщения. Сообщение попадет в процесс только после того, как будет принято полностью.
В режиме {packet, line} данные будут собираться до получения символа перевода строки. Удобно, например, при написании сервера, который обрабатывает данные из терминала. Данные из сокета придут не отдельно по буквам, а уже в виде строки.
Остальные варианты я не пробовал. С ними можно ознакомиться в [1] и [2].
nodelay {nodelay, true|false} понятно без перевода. Значение типа boolean.buffer Размер буферов тоже можно поменять через {buffer, Size}. Причем val (buffer) >= max (val (sndbuf), val (recbuf)). Которые можно задать по отдельности.Про параметры сокетов достаточно.
Хозяин сокета Процесс, который создал сокет, является его хозяином. Но сокет можно легко отдать другому процессу: gen_tcp: controlling_process (Socket, ProcessPID) Это все, что я хотел написать в tcp/ip Erlang шпаргалку.
