2013-10-16 51 views
2

我试图将Pyro的名称服务器转换为一个更方便的对象,该对象将允许我按照自己的意愿启动和停止它。例如,我想用下面的定义解析服务器类能够做到像正确的方式包装Pyro的NameServer

nameServer = NameServer("localhost") 
nameServer.startNS() 

[... make some other operations...] 

nameServer.stopNS()   
nameServer = None 


[... make some other operations...] 

nameServer = NameServer("localhost") 
nameServer.startNS() 

class NameServer(threadutil.Thread): 
    def __init__(self, host, isDeamon=True, port=None, enableBroadcast=True, 
       bchost=None, bcport=None, unixsocket=None, nathost=None, natport=None): 
     super(NameServer,self).__init__() 
     self.setDaemon(isDeamon) 
     self.host=host 
     self.started=threadutil.Event() 
     self.unixsocket = unixsocket 

     self.port = port 
     self.enableBroadcast = enableBroadcast 
     self.bchost = bchost 
     self.bcport = bcport 
     self.nathost = nathost 
     self.natport = natport 


     """ 
     This code is taken from Pyro4.naming.startNSloop 
     """ 
     self.ns_daemon = naming.NameServerDaemon(self.host, self.port, self.unixsocket, 
               nathost=self.nathost, natport=self.natport) 
     self.uri = self.ns_daemon.uriFor(self.ns_daemon.nameserver) 
     internalUri = self.ns_daemon.uriFor(self.ns_daemon.nameserver, nat=False) 
     self.bcserver=None 
     if self.unixsocket: 
      hostip = "Unix domain socket" 
     else: 
      hostip = self.ns_daemon.sock.getsockname()[0] 
      if hostip.startswith("127."): 
       enableBroadcast=False 
      if enableBroadcast: 
       # Make sure to pass the internal uri to the broadcast responder. 
       # It is almost always useless to let it return the external uri, 
       # because external systems won't be able to talk to this thing anyway. 
       bcserver=naming.BroadcastServer(internalUri, self.bchost, self.bcport) 
       bcserver.runInThread() 


    def run(self): 
     try: 
      self.ns_daemon.requestLoop() 
     finally: 
      self.ns_daemon.close() 
      if self.bcserver is not None: 
       self.bcserver.close() 


    def startNS(self): 
     self.start() 

    def stopNS(self): 
     self.ns_daemon.shutdown() 
     if self.bcserver is not None: 
      self.bcserver.shutdown() 

到目前为止,一切都很好。它按预期工作。但是,如果我在名称服务器运行时从另一个线程运行Pyro4.naming.locateNS()命令,那么下次我调用nameServer.stopNS()时,程序将冻结。任何人有一个想法为什么?什么是最好的(至少是更好的)写这样的NameServer包装的方法。

回答

0

Pyro4存储库中有一个示例可供您调整。

https://github.com/delmic/Pyro4/blob/master/examples/eventloop/server.py

from __future__ import print_function 
import socket 
import select 
import sys 
import Pyro4.core 
import Pyro4.naming 

if sys.version_info<(3,0): 
    input=raw_input 

print("Make sure that you don't have a name server running already.") 
servertype=input("Servertype thread/multiplex (t/m)?") 
if servertype=='t': 
    Pyro4.config.SERVERTYPE="thread" 
else: 
    Pyro4.config.SERVERTYPE="multiplex" 

hostname=socket.gethostname() 

class EmbeddedServer(object): 
    def multiply(self, x, y): 
    return x*y 


print("initializing services... servertype=%s" % Pyro4.config.SERVERTYPE) 
# start a name server with broadcast server as well 
nameserverUri, nameserverDaemon, broadcastServer = Pyro4.naming.startNS(host=hostname) 
assert broadcastServer is not None, "expect a broadcast server to be created" 

print("got a Nameserver, uri=%s" % nameserverUri) 
print("ns daemon location string=%s" % nameserverDaemon.locationStr) 
print("ns daemon sockets=%s" % nameserverDaemon.sockets) 
print("bc server socket=%s (fileno %d)" % (broadcastServer.sock, broadcastServer.fileno())) 

# create a Pyro daemon 
pyrodaemon=Pyro4.core.Daemon(host=hostname) 
print("daemon location string=%s" % pyrodaemon.locationStr) 
print("daemon sockets=%s" % pyrodaemon.sockets) 

# register a server object with the daemon 
serveruri=pyrodaemon.register(EmbeddedServer()) 
print("server uri=%s" % serveruri) 

# register it with the embedded nameserver directly 
nameserverDaemon.nameserver.register("example.embedded.server",serveruri) 

print("") 

# below is our custom event loop. 
while True: 
    print("Waiting for events...") 
    # create sets of the socket objects we will be waiting on 
    # (a set provides fast lookup compared to a list) 
    nameserverSockets = set(nameserverDaemon.sockets) 
    pyroSockets = set(pyrodaemon.sockets) 
    rs=[broadcastServer] # only the broadcast server is directly usable as a select() object 
    rs.extend(nameserverSockets) 
    rs.extend(pyroSockets) 
    rs,_,_ = select.select(rs,[],[],3) 
    eventsForNameserver=[] 
    eventsForDaemon=[] 
    for s in rs: 
    if s is broadcastServer: 
     print("Broadcast server received a request") 
     broadcastServer.processRequest() 
    elif s in nameserverSockets: 
     eventsForNameserver.append(s) 
    elif s in pyroSockets: 
     eventsForDaemon.append(s) 
    if eventsForNameserver: 
    print("Nameserver received a request") 
    nameserverDaemon.events(eventsForNameserver) 
    if eventsForDaemon: 
    print("Daemon received a request") 
    pyrodaemon.events(eventsForDaemon) 


nameserverDaemon.close() 
broadcastServer.close() 
pyrodaemon.close() 
print("done")