为了让节点在我的局域网上找到主节点,我让主节点广播一条消息(带有它的IP地址)。它使用Python,没问题,但是使用Elixir我得到一个"地址在使用错误"当试图打开广播套接字时。这里有一些有效的Python代码:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('', 8477))
while True:
msg = s.recvfrom(1024)
print(msg)
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)
所以udpsend.py只是在端口8477上广播一个时间字符串,而udplisten.py会打印它所获得的任何内容。没有端口"地址在使用"运行此代码时出现冲突,无论先启动哪两个程序。
现在,如果我运行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中的套接字设置中的某些东西需要在Elixir中以相同的方式设置,但我似乎无法在gen_udp文档中找到正确的选项。如何在Elixir中打开一个套接字进行广播,它与Python中的udpsend.py例程一样?
我也很高兴接受Erlang的回答。
答案 0 :(得分:2)
正如here所述,使用UDP,您不会打开&#34;连接到地址/端口,只需将数据发送到地址/端口即可。在Erlang中,这是使用:gen_udp.send/4
来完成的,它接受套接字,地址,端口和数据。
如果我在一个shell中启动python udplisten.py
并从另一个shell运行以下命令:
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
我在第一个shell中打印出来:
('hello!', ('127.0.0.1', 54182))