尝试从 Erlang / Elixir 进行 UPD 广播时出现"地址正在使用"错误



为了使节点在我的局域网网络上找到主节点,我得到了主节点来广播消息(使用它的IP地址(。它正在与Python一起使用,没问题,但是对于Elixir,我在尝试打开广播插座时会获得"使用错误的地址"。并附有一些有效的Python代码:

udplisten.py:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('', 8477))
while True:
    msg = s.recvfrom(1024)
    print(msg)

udpsend.py:

import socket 
import time
from datetime import datetime
cs = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
cs.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
cs.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
while True:
    cs.sendto(str(datetime.utcnow()).encode(), ('255.255.255.255', 8477)) # broadcast my address!  
    time.sleep(0.5)

so udpsend.py只需在端口8477上广播一个时间字符串,而udplisten.py py print thrict it it it it it it it it it it it it的。运行此代码时,没有端口"使用中的地址"冲突,无论两个程序中的哪个启动。

现在,如果我运行udplisten.py,然后尝试打开Elixir中的UDP插座:

tbrowne@calculon:~/Dropbox/code/elixir/xxmaster/lib/priv$ iex
Erlang/OTP 20 [erts-9.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (1.5.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> {:ok, sock} = :gen_udp.open(8477, [broadcast: true, reuseaddr: true])
** (MatchError) no match of right hand side value: {:error, :eaddrinuse}

我得到:错误元组:eaddrinuse。

请注意,如果Udplisten.py不运行,我不会得到这个:

iex(1)> {:ok, sock} = :gen_udp.open(8477, [broadcast: true, reuseaddr: true])
{:ok, #Port<0.1291>}
iex(2)> 

但是现在我的udplisten.py不起作用:

tbrowne@calculon:~/Dropbox/code/elixir/xxmaster/lib/priv$ python udplisten.py
Traceback (most recent call last):
  File "udplisten.py", line 3, in <module>
    s.bind(('', 8477))
OSError: [Errno 98] Address already in use

很明显,我在Python中的套接字设置中需要以相同的方式设置python的设置,但我似乎在gen_udp文档中找不到正确的选项。我如何打开Elixir中的插座,以进行广播,该插座的工作原理与我的Udpsend.py例程相同?

我也很高兴接受Erlang的答案。

如下所述,使用UDP,您不"打开"到地址/端口的连接,您只需将数据发送到地址/端口即可。在Erlang中,这是使用接受套接字,地址,端口和数据的:gen_udp.send/4完成的。

如果我在一个外壳中启动python udplisten.py并从另一个外壳中运行以下内容:

iex(1)> {:ok, socket} = :gen_udp.open(0, [broadcast: true])
{:ok, #Port<0.1338>}
iex(2)> :gen_udp.send(socket, '255.255.255.255', 8477, "hello!")
:ok

我在第一个外壳中打印出来:

('hello!', ('127.0.0.1', 54182))

最新更新