2009-02-20 39 views
4

我正在尋找一種方式讓局域網中的客戶端找到我的服務器應用程序的所有實例,而無需進行任何配置。我不想自己剽竊某些東西,而想使用現有的解決方案。就我個人而言,我需要用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) 

回答

3

我寫了一個匹配所有這些標準的應用程序/庫(目前是Python和CLI接口)。它叫做minusconf。變成分叉甚至沒有必要。

1

我假設你擁有對客戶機應用程序的控制,而不僅僅是服務器的應用程序,在這種情況下Pyro可能會爲你工作。

靈活:使用非特權端口。

固體:它已被很好的維護多年。

Portable:純Python,並在多個平臺上進行了良好測試。

Light:我認爲Pyro對於你所得到的東西很輕。也許要求一個Python腳本對於網絡命名服務是不現實的?

即使您不想實際使用Pyro的「遠程對象」範例,您仍然可以使用其命名服務。

+0

煙火看起來不錯,但不能滿足一些要求我滑向「實」:它使用中央服務器來存儲的廣告,使整個網絡龍骨,只要我分開中央服務器子網中的。另外,這是令人難以置信的強大,因此不完全光。而且播出很難看。 – phihag 2009-02-20 15:03:05

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()