Erlang - Puertos

En Erlang, los puertos se utilizan para la comunicación entre diferentes programas. Un socket es un punto final de comunicación que permite que las máquinas se comuniquen a través de Internet mediante el protocolo de Internet (IP).

Tipos de protocolos utilizados en los puertos

Hay 2 tipos de protocolos disponibles para la comunicación. Uno es UDP y el otro es TCP. UDP permite que las aplicaciones se envíen mensajes cortos (llamados datagramas) entre sí, pero no hay garantía de entrega de estos mensajes. También pueden llegar fuera de servicio. TCP, por otro lado, proporciona un flujo confiable de bytes que se entregan en orden siempre que se establezca la conexión.

Veamos un ejemplo simple de abrir un puerto usando UDP.

Ejemplo

-module(helloworld). 
-export([start/0]). 

start() -> 
   {ok, Socket} = gen_udp:open(8789), 
   io:fwrite("~p",[Socket]).

Las siguientes cosas deben tenerse en cuenta sobre el programa anterior

  • los gen_udp contiene los módulos en Erlang utilizados para la comunicación UDP.

  • Aquí 8789 es el número de puerto que se abre en Erlang. Debe asegurarse de que este número de puerto esté disponible y pueda utilizarse.

La salida del programa anterior es:

#Port<0.376>

Envío de un mensaje en el puerto

Una vez que se ha abierto el puerto, se puede enviar un mensaje en el puerto. Esto se hace mediante el método de envío. Veamos la sintaxis y el siguiente ejemplo.

Sintaxis

send(Socket, Address, Port, Packet)

Parámetros

  • Socket - Este es el socket creado con el comando gen_udp: open.

  • Address - Esta es la dirección de la máquina a la que se debe enviar el mensaje.

  • port - Este es el puerto no en el que se debe enviar el mensaje.

  • Packet - Estos son los detalles del paquete o mensaje que se debe enviar.

Valores devueltos

Se devuelve un mensaje correcto si el mensaje se envió correctamente.

Por ejemplo

-module(helloworld). 
-export([start/0]). 

start() ->
   {ok, Socket} = gen_udp:open(8789), 
   io:fwrite("~p",[Socket]), 
   io:fwrite("~p",[gen_udp:send 
   (Socket,"localhost",8789,"Hello")]).

Salida

La salida del programa anterior será la siguiente.

#Port<0.376>ok

Recibir un mensaje en el puerto

Una vez que se ha abierto el puerto, también se puede recibir un mensaje en el puerto. Esto se hace a través delrecv method. Veamos la sintaxis y el siguiente ejemplo.

Sintaxis

recv(Socket, length)

Parámetros

  • Socket - Este es el socket creado con el comando gen_udp: open.

  • Length - Ésta es la longitud del mensaje que se necesita recibir.

Valores devueltos

Se devuelve un mensaje correcto si el mensaje se envió correctamente.

Por ejemplo

-module(helloworld). 
-export([start/0]). 

start() ->
   {ok, Socket} = gen_udp:open(8789), 
   io:fwrite("~p",[Socket]), 
   io:fwrite("~p",[gen_udp:send(Socket,"localhost",8789,"Hello")]),
   io:fwrite("~p",[gen_udp:recv(Socket, 20)]).

El programa completo

Ahora, obviamente, no podemos tener el mismo mensaje de envío y recepción en el mismo programa. Necesita tenerlos definidos en diferentes programas. Así que creemos el siguiente código que crea un componente de servidor que escucha mensajes y un componente de cliente que envía mensajes.

Ejemplo

-module(helloworld). 
-export([start/0,client/1]). 

start() -> 
   spawn(fun() -> server(4000) end).

server(Port) ->
   {ok, Socket} = gen_udp:open(Port, [binary, {active, false}]), 
   io:format("server opened socket:~p~n",[Socket]), 
   loop(Socket). 

loop(Socket) ->
   inet:setopts(Socket, [{active, once}]), 
   receive 
      {udp, Socket, Host, Port, Bin} -> 
      io:format("server received:~p~n",[Bin]), 
      gen_udp:send(Socket, Host, Port, Bin), 
      loop(Socket) 
   end. 

client(N) -> 
   {ok, Socket} = gen_udp:open(0, [binary]), 
   io:format("client opened socket=~p~n",[Socket]), 
   ok = gen_udp:send(Socket, "localhost", 4000, N), Value = receive 
      {udp, Socket, _, _, Bin} ->
         io:format("client received:~p~n",[Bin]) after 2000 ->
      0 
   end, 
   
gen_udp:close(Socket), 
Value.

Se deben tener en cuenta las siguientes cosas sobre el programa anterior.

  • Definimos 2 funciones, la primera es servidor. Esto se utilizará para escuchar en el puerto 4000. El segundo es el cliente que se utilizará para enviar el mensaje "Hola" al componente del servidor.

  • El bucle de recepción se utiliza para leer los mensajes enviados dentro de un bucle definido.

Salida

Ahora necesita ejecutar el programa desde 2 ventanas. La primera ventana se utilizará para ejecutar el componente del servidor ejecutando el siguiente código en elerl command line window.

helloworld:start().

Esto mostrará el siguiente resultado en la ventana de la línea de comandos.

server opened socket:#Port<0.2314>

Ahora, en la segunda ventana de la línea de comandos de erl, ejecute el siguiente comando.

Helloworld:client(“<<Hello>>”).

Cuando emita este comando, la siguiente salida se mostrará en la primera ventana de la línea de comandos.

server received:<<"Hello">>