📜 ⬆️ ⬇️

Erlang. TCP / IP socket options

A small cheat sheet for TCP / IP sockets in Erlang in Russian. Everything is taken from here:

1) erlang.org/doc/man/gen_tcp.html
2) www.erlang.org/doc/man/inet.html#setopts-2
3) learnyousomeerlang.com/buckets-of-sockets#tcp-and-udp-brotocols

Just an example:
... -define(TCP_OPTIONS, [binary, {packet, raw}, {active, false}]). ... {ok,Socket} = gen_tcp:listen(Port, ?TCP_OPTIONS), ... 

Socket parameters are specified in an array (list), separated by commas. The order and number of parameters is determined by taste.

Mode, which determines the type of data (mode)


When choosing a mode, we decide how VM Erlang will give us information from the socket:
- binary - in the form of binary data;
- list - as a list
Erlang is considered to work faster with binary data than with lists.
')
Example
The socket received data from three bytes: 01 02 03
 %%    Msg = <<1,2,3>>, %% ,     Msg %%  <<FirstByte, Tail/binary>> = Msg, %% : %%  Msg  1 %%  Tail  <<2,3>> %%   (list) Msg = [1,2,3], %%  %%  [FirstByte|Tail] = Msg, %%       %% : %%  Msg  1 %%  Tail  [2,3] 


The mode of reading data from the socket (active)


This parameter sets the mode and method for reading data from the socket.

In {active, false} mode {active, false} socket works in the so-called passive mode . It is recommended to use with large amounts of data and high speeds; in cases where different speeds of the network at the client and server; so that the client does not mess up the server. And all because in this mode tcp / ip flow control is used (opening for me).

Data is read directly from the socket.
 recv(Socket) -> case gen_tcp:recv(Socket, 0) of {ok, RcvdData} -> %% RcvdData -   recv(Sock); {error, closed} -> %%  {error, closed} end. 

In {active, true} mode {active, true} data received from the socket is sent to the process as messages. But the flow control is not here, so you can fill the receiving side with a large amount of data.

Data from the socket is passed to the process as messages.
 recv(Socket) -> receive {tcp, Socket, RcvdData} -> %% RcvdData -   recv(Sock); {tcp_closed, Socket} -> {error, closed} end. 

In principle, in this case the process will also hang on the receive until the messages are received. But in this case, you can process messages with data not only from the socket, but also from other processes (for example, a message with data that needs to be sent to the socket).

Socket options can be changed on the go
 inet:setopts(Socket, [{active, once}]), 

In {active, once} mode {active, once} socket is in active mode until the first message is received. After that, it goes into passive mode with flow control (tcp flow control). This is the case when we want to receive socket data as messages and at the same time we need flow control. Every time we want to receive data, we need to change the active property of the socket.
 recv(Socket) -> inet:setopts(Socket, [{active, once}]), receive {tcp, Socket, RcvdData} -> %% RcvdData -   recv(Sock); {tcp_closed, Socket} -> {error, closed} end. 


In addition to once you can specify a number. Read more in the documentation.

packet


Options for this parameter can be many. I will describe only the most interesting and those that some guys understand wrong.

Data from a socket can be received as a meaningless stream, or in the form of certain packets.

In the {packet,0} or {packet,raw} mode {packet,0} data is not packaged in any way and is transmitted for processing as is.

In the mode {packet,1 | 2 | 4} {packet,1 | 2 | 4} {packet,1 | 2 | 4} before the data is 1, 2 or 4 bytes, which specify the length of the message. The message will get into the process only after it is accepted completely.

In the {packet,line} mode {packet,line} data will be collected until a newline character is received. Conveniently, for example, when writing a server that processes data from the terminal. The data from the socket will not come separately by letter, but already as a string.

I have not tried the other options. They can be found in [ 1 ] and [ 2 ].

nodelay


{nodelay, true|false} understandable without translation. A value of type boolean.

buffer


The size of the buffers can also be changed via {buffer, Size} . Moreover, val(buffer) >= max(val(sndbuf),val(recbuf)) . Which can be set separately.

About socket options enough.

Socket host


The process that created the socket is its master. But the socket can easily be given to another process:
 gen_tcp:controlling_process(Socket, ProcessPID) 


That's all I wanted to write a cheat sheet to tcp / ip Erlang.

Source: https://habr.com/ru/post/219967/


All Articles