简体   繁体   English

Python socketserver将数据发送到多个客户端cpu使用高

[英]Python socketserver send data to multiple clients cpu use high

My code accepts gps data from multiple sources aggregates it and sends it back out to multiple clients connected to a threaded single socket. 我的代码接受来自多个源的gps数据聚合它并将其发送回连接到线程单个套接字的多个客户端。 I got it working but the output threads seem to run off with cpu resources. 我得到了它的工作,但输出线程似乎与cpu资源运行。

if I add code to wait for some data from the client the cpu use disappears but the clients only accept a stream of gps info they don't send anything. 如果我添加代码来等待来自客户端的一些数据cpu使用消失但客户端只接受他们不发送任何东西的gps信息流。

Below is the server code that sends data ok but runs high CPU 下面是发送数据正常但运行高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()

if I change it to below cpu stops but it only outputs data if I send a keystroke. 如果我将其更改为低于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

Is there any way to pause the thread until data is sent? 有没有办法暂停线程,直到发送数据? or can I simulate a received message to trigger a data burst from the main program? 或者我可以模拟收到的消息来触发主程序的数据突发?

The reason it's using 100% CPU is that when you have nothing to write, you just keep spinning as fast as you can until there is something to write: 它使用100%的CPU的原因是,当你什么都没有写,只是一味的快,你可以,直到东西可写纺:

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

To make it not use 100% CPU, you have to find something for it to wait on. 为了使它不使用100%CPU,你必须找到一些东西让它等待。

Your fix does this by waiting on received data, but since you don't normally have any data to receive, this isn't very useful. 您的修复通过等待接收的数据来完成此操作,但由于您通常没有任何数据要接收,因此这不是很有用。 (As you put it, "it only outputs data if I send a keystroke".) (正如你所说,“如果我发送击键,它只输出数据”。)

Meanwhile: 与此同时:

Is there any way to pause the thread until data is sent? 有没有办法暂停线程,直到发送数据?

Sure. 当然。 And you're already doing it. 你已经在做了。 That's what sendall does. 这就是sendall所做的。 But that doesn't help. 但这没有用。 The problem is that once you've sent all of the data, you go back through the loop over and over until there's more data to send. 问题是,一旦你发送了所有数据,你就会一遍又一遍地回到循环中,直到需要发送更多数据。

or can I simulate a received message to trigger a data burst from the main program? 或者我可以模拟收到的消息来触发主程序的数据突发?

Of course, but what would you use to trigger that simulated receive? 当然,但你会用什么来触发模拟接收呢? If you're just going to spin simulating receives as fast as possible, that won't help anything. 如果你只是想尽可能快地旋转模拟接收,那对任何事情都无济于事。

I think what you want here is a condition variable around the data. 我想你想要的是围绕数据的条件变量 Something like this: 像这样的东西:

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 = []

Then, whatever your code is that sets SendData (which you didn't show) looks something like this: 然后,无论您的代码是什么设置SendData (您没有显示)看起来像这样:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM