Гибкое, надежное и портативное сервисное обнаружение - PullRequest
4 голосов
/ 20 февраля 2009

Я ищу способ для клиентов в локальной сети найти все экземпляры моего серверного приложения без какой-либо конфигурации. Вместо того, чтобы что-то взламывать самому, я бы хотел использовать существующее решение. Лично мне нужно, чтобы это было сделано в Python, но я был бы рад услышать о решениях на любом другом языке.

Так почему я не использую avahi или OpenSLP или какое-либо другое Zeroconf / SLP решение? Ну, есть пара дополнительных критериев, и у меня сложилось впечатление, что ни одна из вышеупомянутых систем не соответствует им.

Я ищу решение, которое:

  • Гибкое . Он не должен требовать прав суперпользователя, то есть использовать только порты> 1024.
  • Solid . Он должен разрешать несколько служб одного и того же и разных типов служб на одном компьютере и продолжать рекламировать службы, даже если экземпляр, который запустил сервер рекламы, останавливается или дает сбой.
  • Портативный . Он должен работать почти везде или, по крайней мере, на * 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)

Ответы [ 3 ]

3 голосов
/ 17 марта 2009

Я написал приложение / библиотеку (в настоящее время интерфейс Python и CLI), которая соответствует всем этим критериям. Это называется minusconf . Оказывается, разветвление даже не нужно.

2 голосов
/ 13 августа 2013

Для обнаружения узлов в локальной сети я использовал Twisted и UDP Multicast. Надеюсь, вам это тоже поможет.

Ссылка на искаженную документацию, объясняющую, как это сделать: https://twistedmatrix.com/documents/current/core/howto/udp.html#auto3

Вот базовая реализация сервера / клиента на основе витого кода. Он сам ответит, если вы запустите один раз, но весь проверочный код и дополнительные функции были удалены, чтобы его было проще читать.

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()
1 голос
/ 20 февраля 2009

Я предполагаю, что у вас есть контроль над клиентскими приложениями, а не только с серверным приложением, в этом случае Pyro может хорошо работать для вас.

Гибкий: использует непривилегированные порты.

Твердое вещество: Хорошо сохранилось в течение многих лет.

Портативный: чистый Python и хорошо протестирован на нескольких платформах.

Light: Я думаю, что Pyro - это свет для того, что вы получаете. Может быть, запросить один скрипт на Python нереально для службы сетевых имен?

Даже если вы не хотите на самом деле использовать парадигму «удаленного объекта» Pyro, вы все равно можете просто использовать его службу имен.

...