灵活、可靠、可移植的服务发现

发布于 2024-07-14 02:39:50 字数 1443 浏览 14 评论 0原文

我正在寻找一种方法,让 LAN 中的客户端无需任何配置即可找到服务器应用程序的所有实例。 我不想自己破解某些东西,而是想使用现有的解决方案。 就我个人而言,我需要用 Python 来完成,但我很高兴听到任何其他语言的解决方案。

那么为什么我不使用 avahiOpenSLP 或其他一些 Zeroconf/SLP 解决方案? 嗯,还有一些额外的标准,我的印象是上述两个系统都不符合它们。

我正在寻找一个解决方案:

  • 灵活。 它不能要求超级用户权限,即仅使用>1024 的端口。
  • 坚固。 它必须允许在一台计算机上提供相同和不同服务类型的多个服务,并且即使启动广告服务器的实例停止或崩溃,也必须继续广告服务。
  • 便携式。 它必须几乎在任何地方运行,或者至少在 *BSD、Debian/gentoo/RedHat/SuSe Linux、Mac OS X、Solaris 和 Windows NT 上运行。
  • 。 理想情况下,一个 Python 脚本就是整个解决方案。 我对地址自动配置或类似的东西一点也不感兴趣,尽管我不情愿地接受一个具有许多我不需要的功能的解决方案。 此外,任何一次性设置都是严格禁止的。

我期望这样的事情:

def registerService(service): # (type, port)
    if listen(multicast, someport):
        if fork() == child:
            services = [service]
            for q in queriesToMe():
                if q == DISCOVERY:
                    answer(filter(q.criteria, services))
                elif q == ADVERTISE and q.sender == "localhost":
                    services.append(q.service)
    else:
        advertiseAt("localhost", service)

I am looking for a way for clients in a LAN to find all the instances of my server application without any configuration. Instead of hacking something myself, I'd like to use an existing solution. Personally, I need it to be done in Python, but I'd happy to hear about solutions in any other language.

So why am I not using avahi or OpenSLP or some other Zeroconf/SLP solution? Well, there are a couple of additional criteria, and I'm under the impression neither of the aforementioned systems matches them.

I'm looking for a solution that is:

  • Flexible. It must not require superuser rights, i.e. only use ports>1024.
  • Solid. It must allow multiple services of the same and different service type on a single machine and continue advertising the services even when the instance that started the advertisement server stops or crashes.
  • Portable. It must run nearly everywhere, or at least on *BSD, Debian/gentoo/RedHat/SuSe Linux, Mac OS X, Solaris and Windows NT.
  • Light. Ideally, one Python script would be the whole solution. I'm not in the least interested in address autoconfiguration or something like that, although I'd begrudgingly accept a solution that has lots of features I don't need. Furthermore, any one-time setup is a strict no-no.

I expect something like this:

def registerService(service): # (type, port)
    if listen(multicast, someport):
        if fork() == child:
            services = [service]
            for q in queriesToMe():
                if q == DISCOVERY:
                    answer(filter(q.criteria, services))
                elif q == ADVERTISE and q.sender == "localhost":
                    services.append(q.service)
    else:
        advertiseAt("localhost", service)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

桃扇骨 2024-07-21 02:39:50

我编写了一个符合所有这些条件的应用程序/库(当前是 Python 和 CLI 界面)。 它称为 minusconf。 事实证明分叉甚至没有必要。

I wrote an application/library (currently Python and CLI interface) that matches all these critera. It's called minusconf. Turns out forking is not even necessary.

农村范ル 2024-07-21 02:39:50

对于 LAN 中的节点发现,我使用了 Twisted 和 UDP 多播。 希望它也能帮助你。

链接到解释如何执行此操作的扭曲文档:
https://twistedmatrix.com/documents/current/core/howto/udp .html#auto3

这是基于twisted 代码的服务器/客户端的基本实现。
如果您运行一次,它会自行回答,但所有检查代码和额外功能都被删除,以便使其更易于阅读。

from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor

class MulticastPingPong(DatagramProtocol):
    MULTICAST_ADDR = ('228.0.0.5', 8005)
    CMD_PING = "PING"
    CMD_PONG = "PONG"

    def startProtocol(self):
        """
        Called after protocol has started listening.
        """
        # Set the TTL>1 so multicast will cross router hops:
        self.transport.setTTL(5)
        # Join a specific multicast group:
        self.transport.joinGroup(self.MULTICAST_ADDR[0])

        self.send_alive()

    def send_alive(self):
        """
        Sends a multicast signal asking for clients.
        The receivers will reply if they want to be found.
        """
        self.transport.write(self.CMD_PING, self.MULTICAST_ADDR)

    def datagramReceived(self, datagram, address):
        print "Datagram %s received from %s" % (repr(datagram), repr(address))

        if datagram.startswith(self.CMD_PING):
            # someone publishes itself, we reply that we are here
            self.transport.write(self.CMD_PONG, address)
        elif datagram.startswith(self.CMD_PONG):
            # someone reply to our publish message
            print "Got client: ", address[0], address[1]


if __name__ == '__main__':
    reactor.listenMulticast(8005, MulticastPingPong(), listenMultiple=True)
    reactor.run()

For node discovery in a LAN I've used Twisted and UDP Multicast. Hope it helps you too.

Link to the twisted documentation that explains how to do it:
https://twistedmatrix.com/documents/current/core/howto/udp.html#auto3

Here is a basic implementation of a server/client based in the twisted's code.
It answers itself if you run once, but all the checking code and extra features were removed in order to make it simpler to read.

from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor

class MulticastPingPong(DatagramProtocol):
    MULTICAST_ADDR = ('228.0.0.5', 8005)
    CMD_PING = "PING"
    CMD_PONG = "PONG"

    def startProtocol(self):
        """
        Called after protocol has started listening.
        """
        # Set the TTL>1 so multicast will cross router hops:
        self.transport.setTTL(5)
        # Join a specific multicast group:
        self.transport.joinGroup(self.MULTICAST_ADDR[0])

        self.send_alive()

    def send_alive(self):
        """
        Sends a multicast signal asking for clients.
        The receivers will reply if they want to be found.
        """
        self.transport.write(self.CMD_PING, self.MULTICAST_ADDR)

    def datagramReceived(self, datagram, address):
        print "Datagram %s received from %s" % (repr(datagram), repr(address))

        if datagram.startswith(self.CMD_PING):
            # someone publishes itself, we reply that we are here
            self.transport.write(self.CMD_PONG, address)
        elif datagram.startswith(self.CMD_PONG):
            # someone reply to our publish message
            print "Got client: ", address[0], address[1]


if __name__ == '__main__':
    reactor.listenMulticast(8005, MulticastPingPong(), listenMultiple=True)
    reactor.run()
流云如水 2024-07-21 02:39:50

我假设您可以控制客户端应用程序,而不仅仅是服务器应用程序,在这种情况下 Pyro 可能会很好地工作为你。

灵活:使用非特权端口。

坚固:多年来一直维护良好。

可移植:纯Python,并且在多个平台上经过了良好的测试。

轻:我认为 Pyro 对于你所得到的来说是轻的。 对于网络命名服务来说,也许要求一个 Python 脚本是不现实的?

即使您不想实际使用 Pyro 的“远程对象”范例,您仍然可以只使用它的命名服务。

I assume you have control over the client apps, not just the server app, in which case Pyro might work well for you.

Flexible: uses non privileged ports.

Solid: It has been well maintained for many years.

Portable: pure Python and well tested on multiple platforms.

Light: I think Pyro is light for what you're getting. Maybe asking for one Python script is unrealistic for a network naming service?

Even if you don't want to actually use the "remote object" paradigm of Pyro, you still might be able to just use its naming service.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文