2011-05-05 83 views
2

我使用twisted来创建一个“客户端/服务器”,一个作为客户端来获取一些数据的程序,以及作为服务器来重新发送这些数据或者仅仅发送其他数据给客户。Twisted as a client/server problems

我使用twistd来和我的代码初始化我的工厂看起来像:

application = service.Application('monitorD', uid=0, gid=0) 
factoryMonitord = ServerFactory(p) 
internet.TCPServer(9000, factoryMonitord).setServiceParent(service.IServiceCollection(application)) 
#because I need to send some datas from client factory to clients of serverfactory 
factoryScamd = ClientFactory(factoryMonitord) 
internet.TCPClient("localhost", 8001, factoryScamd).setServiceParent(service.IServiceCollection(application)) 

我的问题是,当客户端部分无法连接(因为服务器是unavaiable),它看起来就像是“堵”我所有的服务器部分。它仍然可以在我的服务器部分和其他客户端之间进行通信,但它确实很慢......(并且当我的客户端部分可以连接时,它的工作正常)。

在此先感谢anyhelp。

编辑:

这里是我的ServerFactory代码(很多无用的代码...):

class ServerFactory(protocol.ServerFactory): 
    protocol = ServerProtocol 

    def __init__(self, portal): 
     #self.tp = ClientFactory.tp 
     self.tp = [] 
     self.portal = portal 
     self.loop_vol_raid_areca = LoopingCall(self.checkVolRaidAreca) 
     self.loop_vol_raid_areca.start(30) 
     self.loop_services = LoopingCall(self.checkServices) 
     self.loop_services.start(30) 

    def buildProtocol(self, addr): 
     p = protocol.ServerFactory.buildProtocol(self, addr) 
     p.portal = self.portal 
     return p 

    def sendList(self, data): 
     if data: 
      if isinstance(data, list): 
       for element in data: 
        if isinstance(element, list): 
         self.clean_data = "".join(element) 
       self.sendToClients(self.clean_data) 

    def sendToClients(self, data): 
     print "SEND to MonitorC from MonitorD, tp:", self.tp 
     if data: 
      for tp in self.tp: 
       self.protocol.sendLine(tp, data) 

    def checkServices(self): 
     self.scamd = threads.deferToThread(checkScamd) 
     self.scamd.addCallback(self.sendToClients) 
     self.httpd = threads.deferToThread(checkHttpd) 
     self.httpd.addCallback(self.sendToClients) 
     self.postgres = threads.deferToThread(checkPostgres) 
     self.postgres.addCallback(self.sendToClients) 

    def checkVolRaidAreca(self): 
     self.vol = threads.deferToThread(check_vol_areca) 
     self.vol.addCallback(self.sendList) 
     self.event = threads.deferToThread(get_last_event_areca) 
     self.event.addCallback(self.sendList) 

而这里的客户厂家有很多无用的代码:

class ClientFactory(protocol.ClientFactory): 
    protocol = ClientProtocol 

    def __init__(self, MonitordFactory): 
     self.tp = MonitordFactory.tp 

    def clientConnectionFailed(self, connector, reason): 
     print "Connection to scamd failed - retrying..." 
     time.sleep(30) 
     connector.connect() 

    def clientConnectionLost(self, connector, reason): 
     print "Connection to scamd lost - retrying..." 
     time.sleep(30) 
     connector.connect() 

    def getCamList(self, data): 
     cams_list = data.split("\x00") 
     self.cams_array = [] 
     for i in cams_list: 
      if str.find(i, "camera") != -1: 
       i = i.split(" ") 
       i = filter(lambda x: len(x)>0, i) 
       self.cams_array.append(i) 

    def checkCams(self, data): 
     data = data.split(" ") 
     for i in self.cams_array: 
      if i[1] == data[2]: 
       if data[3] == "-1": 
        msg = i[6] + " ERREUR -1" 
       if data[3] == "0": 
        msg = i[6] + " ERREUR 0" 
       if data[3] == "1": 
        msg = i[6] + " ERREUR 1" 
       if data[3] == "2": 
        msg = i[6] + " ERREUR 2 (RECO)" 
     return msg 

如果需要更多信息,我会将整个代码发布到pastebin。 AND,我是一个新手在python和扭曲(但我用C或C++代码)

+0

你能告诉我们你的ServerFactory和ClientFactory的实现吗? – stderr 2011-05-05 15:15:38

+0

当然,当然,没有睡眠它的工作更好,仍然有时会有一些连接问题。 – unpythonicguy 2011-05-05 15:51:47

回答

1

有两件事情你应该能够改变从蝙蝠。摆脱time.sleep(30)电话。另外,你大量使用线程池,所以你可能想要增加它的大小。每30秒你创建5个线程,并且因为反应器的线程池大小默认为5,你创建的任何其他线程将最终等待在那些5之后。我想有一堆排队等待的线程可能是为什么你的服务运行缓慢甚至出现阻塞。

在短期内,你可能只是在创建你ServerFactory自己twisted.python.threadpool.Threadpool

class ServerFactory(protocol.ServerFactory): 
    protocol = ServerProtocol 

    def __init__(self, portal): 
     # ... 
     self.threadpool = ThreadPool(25, 50) 

    def checkServices(self): 
     # ... 
     self.postgres = threads.deferToThreadPool(reactor, self.threadpool, checkPostgres) 

但是,从长远来看,只要有可能,你应该考虑使用异步API来处理您的服务。

例如,使用twisted.web.client.Agent可以使您的checkHttpd代码异步。对于PostgreSQL,您可以使用txPostgres。我不熟悉上面的scamd服务,因此使用异步IO连接它可能会更困难(即:您可能必须为该服务编写一个异步版本的协议)。

+0

非常感谢,我不知道线程池限制。无论如何,checkservices只是一个kill(pid,0),只是为了看看进程(或主要工作人员)在这里,所以我认为这不是一个问题,因为它在资源方面是“轻”否? – unpythonicguy 2011-05-05 15:59:35

+0

您甚至可能不需要为os.kill调用使用线程。内部扭曲认为os.kill足够快,只需直接拨打即可。 – 2011-05-05 16:18:50

+0

我尝试过,没错,没有os.kill太棒了。感谢您的提示=) – unpythonicguy 2011-05-06 08:04:01