【问题标题】:Erlang UDP packet not received未收到 Erlang UDP 数据包
【发布时间】:2012-09-01 07:55:11
【问题描述】:

我正在尝试让客户端(在 NAT 之后)将数据包发送到专用服务器。

这是我的代码:

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

我在专用服务器上启动监听功能:

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

在客户端我启动发送循环:

$ 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

虽然来自客户端的 gen_udp:send 返回 ok,但服务器似乎没有收到任何这些数据包,因为它应该打印“server received : "HELLO !!!"" 在控制台上。

任何人都会知道为什么这不起作用。

编辑 1:

  • 专用服务器上没有配置防火墙或iptable。

  • 客户端和服务器之间的连接通过 TCP 工作正常,但不是 UDP。

  • 当我尝试在同一设备(不同的 erlang 节点)上同时运行服务器和客户端时,它也不起作用。

编辑 2: 更改了侦听部分的代码,每次收到消息时都在自身上循环重新创建套接字...但仍然无法正常工作。

【问题讨论】:

  • "ip.to.my.server" 的实际值是多少?您是否仅使用{127.0.0.1} 尝试过?
  • ip "ip.to.my.server" 是这样的字符串:"27.46.35.14"...实际上我应该叫它"ip.of.my.server".. . 已编辑
  • 当我尝试在同一台机器上运行服务器和客户端时......它实际上也不起作用。
  • 啊哈,你修改后的代码更容易看出为什么它不起作用。我将编辑我的答案。

标签: erlang udp


【解决方案1】:

您的 start_client/3send/4 循环应该可以按预期工作,尽管它是一种稍微复杂的方法来获得 1 秒的延迟。

您的listen/1 不会按预期执行,最多应该返回一条消息:

  • 对于每个循环,它都会打开一个新套接字,第一次使用端口打开套接字,而在接下来的循环中,它会使用套接字打开一个新套接字,这会产生错误。
  • 您将套接字设置为{active,once},因此在将套接字重置为活动一次之前,您最多会在套接字上接收一个数据包。

为什么要在接收端尝试做一些简单的事情:

Erlang R15B (erts-5.9) [source] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9  (abort with ^G)
1> {ok,S}=gen_udp:open(5555,[]).
{ok,#Port<0.582>}
2> flush().
Shell got {udp,#Port<0.582>,{127,0,0,1},4444,"hej"}
Shell got {udp,#Port<0.582>,{127,0,0,1},4444,"there"}
ok
3> 

作为测试基本连接的第一步?

编辑:

在您的新版本中,您调用start_listen/1,它会打开一个 UDP 套接字,然后会产生一个进程来坐下来监听它。打开端口的进程是端口控制进程。数据包到达时发送的消息被发送到控制进程,在这种情况下不是控制进程。

有两种方法可以解决这个问题:

  • 生成一个进程,该进程首先打开端口,然后进入一个循环,从套接字接收 UDP 消息。这就是您引用的示例中的完成方式:start 生成一个运行server 的进程,该进程打开端口然后调用loop

  • 使用gen_udp:controlling_process/2 将套接字的控制权传递给循环进程,以便它接收数据包消息。

两者都工作并有自己的位置。您在原始代码中具有相同的结构,但我错过了它。

【讨论】:

  • 感谢您的回答,如果我使用erlycoder.com/83/erlang-udp-socket-usage-example-with-gen_udp,实际上客户端和服务器之间的连接工作正常。错误来自我的代码,实际上我之前已经发现了监听问题,我将编辑我的帖子以显示我所做的更改,但现在仍然无法正常工作......
  • @TheSquad 啊哈,您修改后的代码非常更容易看出它为什么不起作用。我将编辑我的答案。
【解决方案2】:

发现了问题,我正在启动套接字,然后只产生循环......

要么将 control_process 更改为生成的 pid,要么打开生成的 pid 上的套接字。

希望对某人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-22
    • 2022-10-17
    • 2017-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-25
    相关资源
    最近更新 更多