Skip to main content
 首页 » 编程设计

python之扭曲为客户端/服务器问题

2025年05月04日7飞鱼

我正在使用 twisted 来创建一个“客户端/服务器”,该程序作为客户端获取一些数据,并作为服务器重新发送此数据或仅向客户端发送其他数据。

我正在使用 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)) 

我的问题是当客户端无法连接时(因为服务器不可用),看起来它“阻止”了我所有的服务器部分。我的服务器部分和其他客户端之间仍然可以进行通信,但它真的很慢......(当我的客户端部分可以连接时,它就可以正常工作)。

在此先感谢您的帮助。

编辑:

这是我的 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。 而且,我是 python 的新手并且很扭曲(但我曾经用 C 或 C++ 编写代码)

请您参考如下方法:

您应该能够立即更改两件事。去掉 time.sleep(30) 调用。此外,您正在大量使用线程池,因此您可能希望增加它的大小。每 30 秒您创建 5 个线程,并且因为 react 器线程池大小默认为 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 来处理您的服务。

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