Home:ALL Converter>Erlang UDP packet not received

Erlang UDP packet not received

Ask Time:2012-09-07T20:19:58         Author:TheSquad

Json Formatter

I'm trying to get a client (behind a NAT) to send packet to a dedicated server.

Here's my code :

-module(udp_test).

-export([start_client/3, listen/1, send/4, start_listen/1]).

start_client(Host, Port, Packet) ->
    {ok, Socket} = gen_udp:open(0, [{active, true}, binary]),
    io:format("client opened socket=~p~n",[Socket]),
    spawn(?MODULE, send, [Socket, Host, Port, Packet]).

start_listen(Port) ->
    {ok, Socket} = gen_udp:open(Port, [binary]),
    spawn(?MODULE, listen, [Socket]).

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

send(Socket, Host, Port, Packet) ->
    timer:send_after(1000, tryToSend),
    receive
    tryToSend ->
        io:fwrite("Sending: ~p / to ~p / P: ~p~n", [Packet, Host, Port]),
        Val = gen_udp:send(Socket, Host, Port, Packet),
        io:fwrite("Value: ~p~n", [Val]),
        send(Socket, Host, Port, Packet);
    _ ->
        io:fwrite("???~n")
    end.

on the dedicated server I launch the listen function :

# erl -pa ebin
Erlang R15B01 (erts-5.9.1) [source] [64-bit] [smp:4:4] [async-threads:0] [kernel-poll:false]

Eshell V5.9.1  (abort with ^G)
1> udp_test:listen(4000).

on the client side I launch the sending loop :

$ erl -pa ebin                                                      
Erlang R15B (erts-5.9) [source] [smp:2:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9  (abort with ^G)
1> udp_test:start_client("ip.of.my.server", 4000, "HELLO !!!").
client opened socket=#Port<0.737>
<0.33.0>
Sending: "HELLO !!!" / to "ip.of.my.server" / P: 4000
Value: ok
Sending: "HELLO !!!" / to "ip.of.my.server" / P: 4000
Value: ok
Sending: "HELLO !!!" / to "ip.of.my.server" / P: 4000
Value: ok

Although gen_udp:send from the client returns ok, the server doesn't seems to receive any of these packets, as it should print "server received: "HELLO !!!"" on the console.

anyone would have an idea why this is not working.

EDIT 1 :

  • There is no firewall or iptable configured on the dedicated server.

  • The connection works fine through TCP between the client and the server, but not UDP.

  • When I try to run both server and client on the same device (different erlang node), it does not work either.

EDIT 2 : changed the code for the listen part looping on itself re-creating the Socket each time a message is received... but still does not work.

Author:TheSquad,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/12317981/erlang-udp-packet-not-received
rvirding :

Your start_client/3, send/4 loop should work as expected, although it is a slightly convoluted way to get a 1 sec delay.\n\nYour listen/1 will not do as expected and should at most return one message:\n\n\nFor each loop it opens a new socket, the first time it uses the port to open the socket while in the following loops it uses the socket to open a new socket, which should generate an error.\nYou set the socket to {active,once} so you will at most receive one packet on the socket before you reset it to being active once.\n\n\nWhy try on the receiving side doing something simple like:\n\nErlang R15B (erts-5.9) [source] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.9 (abort with ^G)\n1> {ok,S}=gen_udp:open(5555,[]).\n{ok,#Port<0.582>}\n2> flush().\nShell got {udp,#Port<0.582>,{127,0,0,1},4444,\"hej\"}\nShell got {udp,#Port<0.582>,{127,0,0,1},4444,\"there\"}\nok\n3> \n\n\nas a first step to test the basic connection?\n\nEDIT:\n\nIn your new version you call start_listen/1 which opens a UDP socket and then spawns a process to sit and listen on it. The process which opens the port is the ports controlling process. The messages sent when a packet arrives is sent to the controlling process, which in this case is not the controlling process.\n\nThere are two ways to fix this:\n\n\nSpawn a process which first opens the port and and then goes into a loop receiving the UDP messages from the socket. This is how it is done in the example you referenced: start spawns a process running server which opens the port and then calls loop.\nUse gen_udp:controlling_process/2 to pass control of the socket to the loop process so it will receive the packet messages.\n\n\nBoth work and have their place. You had the same structure in the original code but I missed it.",
2012-09-07T13:07:37
yy