3

我对 simpleXMLRPC 服务器有疑问。我的程序中有一台服务器,可以从另一台服务器访问。让我们将服务器称为具有 simpleXMLServer 实例的计算机,将客户端称为另一台服务器。

所以当客户端连接到我的服务器时,服务器会调用服务器中的一个函数。此功能有时可能需要很长时间才能执行(至 5 分钟),然后发送一条长消息。

class Report(object):    
    __instance = None

    def __new__(self):
        if self.__instance is None:
            self.__instance = object.__new__(self)
            self.__instance.__init()
        return self.__instance

    def __init(self):
        self._lastRequestTime = 0
        self._lastRequest     = ''
        self._minInterval     = 1
        self._timeout         = 2
        self.__lock           = Utils.Threading.Lock()
        self.__lockEvent      = Utils.Threading.Lock()
        self._event           = Utils.Threading.Event()
        reportThread = threading.Thread(name   = 'reportThread',
                                        target = self.reportLoop)
        reportThread.start()

    def _reportAll(self):
        tmp = Somewhere.reportAll()
        try:
            self.__lock.acquire()
            self._lastRequest = tmp
        finally:
            self.__lock.release()

    def reportLoop(self):
        while 1:
            self._event.wait()
            self._reportAll()
            try:
                self.__lockEvent.acquire()
                self._event.clear()
            finally:
                self.__lockEvent.release()

    def reportAll(self):
        if abs(Utils.Time.time() - self._lastRequestTime) > self._minInterval or len(self._lastRequest) == 0:
            self._lastRequestTime = time.time()
        else:
            return self._lastRequest

        try:
            self.__lockEvent.acquire()
            self._event.set()    
        finally:
            self.__lockEvent.release()

        try:
            self.__lock.acquire()
            return self._lastRequest
        finally:
            self.__lock.release()

这是我创建服务器的方式:

def startListen(self):
    logging.basicConfig(level = logging.DEBUG)
    try:
        # Create server
        self._server = SimpleXMLRPCServer(("192.168.0.57", 49007), requestHandler=RequestHandler)
        self._server.register_introspection_functions()
        self._server.register_function(Report().reportAll, 'reportAll')
        self._server.serve_forever()
    except:
        return self.restart()

为了避免在客户端服务器中长时间等待(这可能会冻结客户端程序),我在客户端服务器中创建了一个信号,该信号会在 5 秒后停止客户端线程(我的客户端实际上是守护进程 gmond 的一个实例)神经节)。那是客户端的代码:

def getMessage(self):

    def timeoutHandler(signum, frame):
        raise Exceptions.BFException('Timeout  %d s lasted' % defaultTimeout)

    self._client = None
    msg = None

    # To be sure that will not freeze, we set a signal
    signal.signal(signal.SIGALRM, timeoutHandler)
    signal.alarm(defaultTimeout)

    try:
        self._client = xmlrpclib.ServerProxy('http://192.168.0.57:49007')
        msg = self._client.reportAll() 
    except:
        print 'The connection has not been established'
        self._client = None
        msg = None
    finally:
        signal.alarm(0)
        return msg

然而,无论我做什么,有时它会完全冻结,我得到那个错误:

Exception happened during processing of request from ('192.168.0.85', 55417)
Traceback (most recent call last):
  File "C:\Python26\lib\SocketServer.py", line 283, in _handle_request_noblock
    self.process_request(request, client_address)
  File "C:\Python26\lib\SocketServer.py", line 309, in process_request
    self.finish_request(request, client_address)
  File "C:\Python26\lib\SocketServer.py", line 322, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "C:\Python26\lib\SocketServer.py", line 617, in __init__
    self.handle()
  File "C:\Python26\lib\BaseHTTPServer.py", line 329, in handle
    self.handle_one_request()
  File "C:\Python26\lib\BaseHTTPServer.py", line 323, in handle_one_request
    method()
  File "C:\Python26\lib\SimpleXMLRPCServer.py", line 491, in do_POST
    self.wfile.write(response)
  File "C:\Python26\lib\socket.py", line 318, in write
    self.flush()
  File "C:\Python26\lib\socket.py", line 297, in flush
    self._sock.sendall(buffer(data, write_offset, buffer_size))
error: [Errno 10053] Une connexion établie a été abandonnée par un logiciel de votre ordinateur hôte

如果我在 Debian 发行版中做同样的事情,我会得到同样的错误,除了我得到:[Errno 32] Broken Pipe

无论我做什么,如果再次调用此服务器,我总是在第一次收到此错误后收到此错误,并且根本没有响应。我不知道该怎么处理。我已经被困了好几天了...

有人可以帮我吗?

谢谢

4

2 回答 2

0

为什么不在客户端机器上运行 simpleXMLRPC 服务器,并使用工作线程和队列实现您的原始服务器。您的原始服务器会将参数推送到队列并立即返回。工作线程等待队列并在数据可用时执行。完成后,它将数据作为远程过程调用的参数发送回客户端,其方式与从客户端接收调用的方式完全相同。

这样做意味着客户端和服务器都不会阻塞。

于 2013-10-03T10:15:38.123 回答
0

基本上,您正在终止客户端的连接,因此服务器报告连接已终止。

我不确定为什么在那之后您没有得到任何响应,但要考虑的一件事是服务器是单线程的,因此在运行缓慢的操作时无法处理其他连接。

另请注意,信号可能不会与对 的调用传递到同一线程signal(),因此这可能会给您带来问题,除非 python 在幕后做了一些魔术来确保通知正确的线程。同样,我不确定是否普遍允许抛出异常,当然,从 C 中,你不应该期望总是在主堆栈上。

于 2011-07-19T10:44:23.793 回答