gen_udp 在 Elixir 中无法连接到 UDP 套接字
gen_udp in Elixir fails to connect to a UDP socket
我正在尝试让 Graphitex(Elixir 的 Graphite Carbon API 客户端)使用 gen_udp
而不是 gen_tcp
。
客户端是一个包裹了UDP套接字的GenServer,public API与问题无关
违规位似乎是 connect/1
、terminate/2
和 handle_cast/2
GenServer 回调。
可以找到原始实现 here, my fork is here。
我做了什么:
- 用
:gen_udp.open(0, opts)
替换了:gen_tcp.connect(host, port, opts)
(其中host
和port
是远程Graphite Carbon UDP端点的那些)(以获得OS-选择的端口)
- 将
:gen_tcp.send(socket, msg)
替换为 :gen_udp.send(socket, host, port, msg)
以通过 OS-选择的 UDP 套接字 将 msg
发送到远程 host:port
当 运行 使用我的 graphitex
分支的应用程序时出现的错误:
12:12:14.160 [info] Connecting to carbon at localhost:2003
12:12:14.383 [error] GenServer Graphitex.Client terminating
** (FunctionClauseError) no function clause matching in Graphitex.Client.terminate/2
(graphitex) lib/graphitex/client.ex:78: Graphitex.Client.terminate({{:badmatch, {:error, :econnrefused}}, [{Graphitex.Client, :connect, 1, [file: 'lib/graphitex/client.ex', line: 73]}, {Graphitex.Client, :handle_cast, 2, [file: 'lib/graphitex/client.ex', line: 86]}, {:gen_server, :try_dispatch, 4, [file: 'gen_server.erl', line: 637]}, {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 711]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}]}, %{socket: nil})
(stdlib) gen_server.erl:673: :gen_server.try_terminate/3
(stdlib) gen_server.erl:858: :gen_server.terminate/10
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", {:metric, 'graphite_consumer 1000 1570525934\n'}}
State: %{socket: nil}
似乎套接字(我在 connect/1
中明确设置的状态)似乎是 nil
。我很困惑为什么会这样; :gen_udp.open(0)
在 IEx 中工作正常并且 returns {:ok, socket}
.
UDP是无连接协议,意味着你不需要连接到远程套接字来发送数据。您需要做的就是:
{:ok, socket} = :gen_udp.open(0)
:ok = :gen_udp.send(socket, host, port, msg)
不需要连接,这就是为什么 :gen_udp.connect
没有文档的原因,因为根本不应该使用它。
我正在尝试让 Graphitex(Elixir 的 Graphite Carbon API 客户端)使用 gen_udp
而不是 gen_tcp
。
客户端是一个包裹了UDP套接字的GenServer,public API与问题无关
违规位似乎是 connect/1
、terminate/2
和 handle_cast/2
GenServer 回调。
可以找到原始实现 here, my fork is here。
我做了什么:
- 用
:gen_udp.open(0, opts)
替换了:gen_tcp.connect(host, port, opts)
(其中host
和port
是远程Graphite Carbon UDP端点的那些)(以获得OS-选择的端口) - 将
:gen_tcp.send(socket, msg)
替换为:gen_udp.send(socket, host, port, msg)
以通过 OS-选择的 UDP 套接字 将
msg
发送到远程 host:port
当 运行 使用我的 graphitex
分支的应用程序时出现的错误:
12:12:14.160 [info] Connecting to carbon at localhost:2003
12:12:14.383 [error] GenServer Graphitex.Client terminating
** (FunctionClauseError) no function clause matching in Graphitex.Client.terminate/2
(graphitex) lib/graphitex/client.ex:78: Graphitex.Client.terminate({{:badmatch, {:error, :econnrefused}}, [{Graphitex.Client, :connect, 1, [file: 'lib/graphitex/client.ex', line: 73]}, {Graphitex.Client, :handle_cast, 2, [file: 'lib/graphitex/client.ex', line: 86]}, {:gen_server, :try_dispatch, 4, [file: 'gen_server.erl', line: 637]}, {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 711]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}]}, %{socket: nil})
(stdlib) gen_server.erl:673: :gen_server.try_terminate/3
(stdlib) gen_server.erl:858: :gen_server.terminate/10
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", {:metric, 'graphite_consumer 1000 1570525934\n'}}
State: %{socket: nil}
似乎套接字(我在 connect/1
中明确设置的状态)似乎是 nil
。我很困惑为什么会这样; :gen_udp.open(0)
在 IEx 中工作正常并且 returns {:ok, socket}
.
UDP是无连接协议,意味着你不需要连接到远程套接字来发送数据。您需要做的就是:
{:ok, socket} = :gen_udp.open(0)
:ok = :gen_udp.send(socket, host, port, msg)
不需要连接,这就是为什么 :gen_udp.connect
没有文档的原因,因为根本不应该使用它。