Erlang - Ports



In Erlang, ports are used for communication between different programs. A socket is a communication endpoint that allows machines to communicate over the Internet by using the Internet Protocol (IP).

Types of Protocols Used in Ports

There are 2 types of protocols available for communication. One is UDP and the other is TCP. UDP lets applications send short messages (called datagrams) to each other, but there is no guarantee of delivery for these messages. They can also arrive out of order. TCP, on the other hand, provides a reliable stream of bytes that are delivered in order as long as the connection is established.

Let’s look at a simple example of opening a port using UDP.

Example

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

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

The following things need to be noted about the above program

  • The gen_udp contains the modules in Erlang used for UDP communication.

  • Here 8789 is the port number which is being opened in Erlang. You need to make sure this port number is available and can be used.

The output of the above program is −

#Port<0.376>

Sending a Message on the Port

Once the port has been opened a message can be sent on the port. This is done via the send method. Let’s look at the syntax and the following example.

Syntax

send(Socket, Address, Port, Packet)

Parameters

  • Socket − This is the socket created with the gen_udp:open command.

  • Address − This is machine address to where the message has to be sent to.

  • port − This is the port no on which the message needs to be sent.

  • Packet − This is the packet or message details which needs to be sent.

Return Values

An ok message is returned if the message was sent properly.

For example

-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")]).

Output

The output of the above program will be as follows.

#Port<0.376>ok

Receiving a Message on the Port

Once the port has been opened a message can also be received on the port. This is done via the recv method. Let’s look at the syntax and the following example.

Syntax

recv(Socket, length)

Parameters

  • Socket − This is the socket created with the gen_udp:open command.

  • Length − This is the length of the message which needs to be received.

Return Values

An ok message is returned if the message was sent properly.

For example

-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)]).

The Complete Program

Now obviously we cannot have the same send and receive message in the same program. You need to have them defined in different programs. So let create the following code which creates a server component that listens to messages and a client component which sends messages.

Example

-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.

The following things need to be noted about the above program.

  • We define 2 functions, the first is server. This will be used to listen on the port 4000. The second is the client which will be used to send the message “Hello” to the server component.

  • The receive loop is used to read the messages sent within a define loop.

Output

Now you need to run the program from 2 windows. The first window will be used to run the server component by running the following code in the erl command line window.

helloworld:start().

This will display the following output in the command line window.

server opened socket:#Port<0.2314>

Now in the second erl command line window, run the following command.

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

When you issue this command, the following output will be displayed in the first command line window.

server received:<<"Hello">>
Advertisements