Python服务发现:在本地网络中宣传服务

19

我有一个“服务器”python脚本在本地网络中的一台机器上运行,它等待客户端连接并将一些工作交给他们。服务器和客户端代码都已编写并正常工作...

问题是,该服务器可能从本地网络中任何一台机器上运行,因此我不能在脚本中硬编码地址...我立即想知道是否可以让一台机器宣传其存在,然后客户端可以回应。在Python的标准库中是否可行?不幸的是,我真的没有时间下载Twisted或Tornado并学习它们,所以我需要简单的东西。

我试着再考虑一下,意识到我可以有一台单独的静态IP机器,服务器可以向其注册/注销,客户端可以从该机器上查找服务器。就像一个种子追踪器一样。如果无法轻松地执行服务广告方法,则必须这样做。


1
一种常见的本地服务发现方式是使用网络广播。如果您使用它,就不需要硬编码特定的IP地址,也不需要中央服务。 - loopbackbee
我不确定在Python中这是否容易或困难,但处理它的一种方法是通过多播DNS。 - cnicutar
@ goncalopp 谢谢,我稍微研究了一下,发现这些教程通常会使用外部库,比较深入。我会尝试研究多播 DNS。 - Mazyod
@Mazyod,实际上这很容易。如果您还没有熟悉Berkeley sockets,请花些时间了解一下。 - loopbackbee
@goncalopp 很好!你能把它添加为答案,这样其他人就可以轻松找到了吗?谢谢。 - Mazyod
@goncalopp 对的,我在 Python socket programming 中读到了它们。这是一个开始,但我想我应该学习更多关于这个的知识。 - Mazyod
1个回答

29
在本地网络上进行服务公告/发现的简便方法是通过广播UDP数据包。
常量:
PORT = 50000
MAGIC = "fna349fn" #to make sure we don't confuse or get confused by other programs

公告:

from time import sleep
from socket import socket, AF_INET, SOCK_DGRAM, SOL_SOCKET, SO_BROADCAST, gethostbyname, gethostname

s = socket(AF_INET, SOCK_DGRAM) #create UDP socket
s.bind(('', 0))
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) #this is a broadcast socket
my_ip= gethostbyname(gethostname()) #get our IP. Be careful if you have multiple network interfaces or IPs

while 1:
    data = MAGIC+my_ip
    s.sendto(data, ('<broadcast>', PORT))
    print "sent service announcement"
    sleep(5)

发现:

from socket import socket, AF_INET, SOCK_DGRAM

s = socket(AF_INET, SOCK_DGRAM) #create UDP socket
s.bind(('', PORT))

while 1:
    data, addr = s.recvfrom(1024) #wait for a packet
    if data.startswith(MAGIC):
        print "got service announcement from", data[len(MAGIC):]

这段代码是从python.org的演示代码broadcast.py中改编而来。

有没有办法让这个工作,使得发现方不知道宣告者在哪个端口上? - Salim Fadhley
1
@SalimFadhley TCP/UDP通信总是在主机、端口对上进行的,所以我猜想除了依次尝试所有端口或捕获接口上的所有流量外,没有其他方法可以实现(指定随机端口)。您不能使用固定的(高)端口吗? - loopbackbee
1
比那些 SSDP、UPnP、SLP 等等都要好得多。谢谢。 - Epoc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接