2009-02-20 5 views
4

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

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

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

  • Гибкая. Он не должен требовать прав суперпользователя, т. Е. Использовать только порты> 1024.
  • Solid. Он должен разрешать нескольким службам одного и того же типа обслуживания на одном компьютере и продолжать рекламировать сервисы, даже если экземпляр, который запустил сервер рекламы, останавливается или падает.
  • Портативный. Он должен работать почти везде или, по крайней мере, на * BSD, Debian/gentoo/RedHat/SuSe Linux, Mac OS X, Solaris и Windows NT.
  • Light. В идеале один скрипт 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

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

1

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

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

Solid: Он был в хорошем состоянии в течение многих лет.

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

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

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

+0

Pyro выглядит великолепно, но не в состоянии удовлетворить некоторые требования, я скользил в «Solid»: Он использует центральный сервер для хранения рекламы, так что вся сеть кили над как только отделить центральную подсеть сервера. Кроме того, он невероятно мощный и, следовательно, не совсем свет. И трансляция уродливая. – phihag

+0

(Я подозреваю, что настоящая проблема - я слишком требовательна) – phihag

2

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

Ссылка на витую документацию, которая объясняет, как это сделать: 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()