无意中看到了stackoverflow.com 中提出的有关erlang UDP收发数据的问题,自己也一知半解,故直接敲代码重现问题以便修正。
stackoverflow.com 中有问题代码:
-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.
出现的问题是:应用程序中,以下两句代码并未执行。
gen_udp:send(Socket, Host, Port, "Got Message"),
io:format("server received:~p / ~p~n",[Socket, Bin]),
帖子给出的回答是:
- For 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.
- You 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.
-module(udp_test2).
-export([server/0,start_server/0,listen/1,client/1,start_client/1, send/4]).
server() ->
spawn(?MODULE,start_server,[]).
start_server() ->
{ok, Socket} = gen_udp:open(4000, [binary]),
listen(Socket).
listen(Socket) ->
inet:setopts(Socket, [{active, once}]),
receive
{udp, Socket , Host, Port, Bin} ->
gen_udp:send(Socket, Host, Port, Bin),
io:format("server received message:~p / ~p~n",[Socket, Bin]),
listen(Socket)
end.
client(Msg) ->
spawn(?MODULE,start_client,[Msg]).
start_client(Msg) ->
{ok, Socket} = gen_udp:open(0, [{active, true}, binary]),
io:format("client opened socket=~p~n",[Socket]),
send(Socket, "127.0.0.1", 4000, Msg).
send(Socket, Host, Port, Msg) ->
timer:send_after(1000, tryToSend),
receive
tryToSend ->
io:fwrite("~nSending: ~p / to ~p / P: ~p~n", [Msg, Host, Port]),
gen_udp:send(Socket, Host, Port, Msg),
send(Socket, Host, Port, Msg);
{udp,Socket,_,_,Bin} ->
io:fwrite("client received message: ~p / ~p~n",[Socket,Bin])
end.