【问题标题】:Python socketserver send data to multiple clients cpu use highPython socketserver 向多个客户端发送数据 cpu 使用率高
【发布时间】:2013-04-17 08:00:51
【问题描述】:

我的代码接受来自多个来源的 gps 数据,将其聚合并将其发送回连接到线程单套接字的多个客户端。我让它工作了,但输出线程似乎耗尽了 cpu 资源。

如果我添加代码来等待来自客户端的一些数据,cpu 使用就会消失,但客户端只接受 gps 信息流,它们不会发送任何内容。

以下是发送数据正常但运行 CPU 较高的服务器代码

class ThreadedServerRequestHandler(SocketServer.StreamRequestHandler):

    def handle(self):
        global SendData
        global SendNow
        while True:
            SendNow
            for line in SendData:
                self.request.sendall(line)
                SendData = []
                SendNow = False
        return

class ServerThread(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    daemon_threads = True
    allow_reuse_address = True

if __name__ == '__main__':
    import socket
    import threading

    address = TxServer
    server = ServerThread(address, ThreadedServerRequestHandler)

    t = threading.Thread(target=server.serve_forever)
    t.setDaemon(True) # don't hang on exit
    t.start()

如果我将其更改为低于 cpu 停止但它仅在我发送击键时输出数据。

class ThreadedServerRequestHandler(SocketServer.StreamRequestHandler):

    def handle(self):
        global SendData
        global SendNow
        while True:
            self.data = self.request.recv(1024).strip()
            if self.data == '':
                print 'closing thread'            
                break
            while SendNow == True:
                for line in SendData:
                    self.request.sendall(line)
                SendData = []
                SendNow = False
        return

有什么方法可以暂停线程直到发送数据?或者我可以模拟接收到的消息来触发主程序的数据突发吗?

【问题讨论】:

    标签: python multithreading cpu-usage socketserver


    【解决方案1】:

    它使用 100% 的 CPU 的原因是,当你没有什么可写的时候,你只是尽可能快地旋转直到 有东西要写:

    while True:
        SendNow
        for line in SendData:
            self.request.sendall(line)
            SendData = []
            SendNow = False
    

    要让它不使用 100% CPU,你必须找到让它等待的东西。

    您的修复方法是等待接收到的数据,但由于您通常没有任何数据要接收,因此这不是很有用。 (正如你所说,“它只有在我发送击键时才会输出数据”。)

    同时:

    有什么方法可以暂停线程直到发送数据?

    当然。而你已经在这样做了。这就是sendall 所做的。但这无济于事。问题是,一旦您发送了所有数据,您就会一遍又一遍地返回循环,直到有更多数据要发送。

    或者我可以模拟接收到的消息来触发主程序的数据突发吗?

    当然可以,但是你会用什么来触发模拟接收呢?如果您只是要尽可能快地旋转模拟接收,那将无济于事。

    我认为您在这里想要的是围绕数据的condition variable。像这样的:

    SendCondition = threading.Condition()
    
    class ThreadedServerRequestHandler(SocketServer.StreamRequestHandler):
    
        def handle(self):
            global SendCondition
            global SendData
            while True:
                with SendCondition:
                    while not SendData:
                        SendCondition.wait()
                    for line in SendData:
                        self.request.sendall(line)
                    SendData = []
    

    然后,无论你的代码是什么,设置SendData(你没有显示)看起来像这样:

    global SendCondition
    global SendData
    # ...
    new_send_data = <whatever>
    with SendCondition:
        SendData.append(new_send_data)
        SendCondition.notify()
    

    【讨论】:

    • 很棒,就像一个魅力。这就是谷歌编程的问题,我不知道我不知道什么,所以我的搜索问题受限于我已经了解的内容。
    • @user2304910:这就是为什么值得通过教程而不是仅仅获取示例代码并试图弄清楚它的原因。问题是通常没有任何关于你想要做的事情的好的教程。而且,如果有的话,很难找到。 (我确定有人写了一篇很棒的“Python 线程间安全共享数据的不同方式简介”,但我不知道在哪里可以找到它……)
    猜你喜欢
    • 2011-04-09
    • 1970-01-01
    • 2014-03-08
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 2013-02-01
    • 2017-05-07
    • 1970-01-01
    相关资源
    最近更新 更多