質問

My code accepts gps data from multiple sources aggregates it and sends it back out to multiple clients connected to a threaded single socket. I got it working but the output threads seem to run off with cpu resources.

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.

Below is the server code that sends data ok but runs high 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.

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:

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.

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. 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:

global SendCondition
global SendData
# ...
new_send_data = <whatever>
with SendCondition:
    SendData.append(new_send_data)
    SendCondition.notify()
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top