python sockets stop recv from hanging?

2020-02-26 10:17发布

问题:

I am trying to create a two player game in pygame using sockets, the thing is, when I try to receive data on on this line:

message = self.conn.recv(1024)

python hangs until it gets some data. The problem with this is that is pauses the game loop when the client is not sending anything through the socket and causes a black screen. How can I stop recv from doing this?

Thanks in advance

回答1:

Use nonblocking mode. (See socket.setblocking.)

Or check if there is data available before call recv. For example, using select.select:

r, _, _ = select.select([self.conn], [], [])
if r:
    # ready to receive
    message = self.conn.recv(1024)


回答2:

you can use signal module to stop an hangs recv thread.

in recv thread:

try:
    data = sock.recv(1024)
except KeyboardInterrupt:
    pass

in interpret thread:

signal.pthread_kill(your_recving_thread.ident, signal.SIGINT)


回答3:

I know that this is an old post, but since I worked on a similar project lately, I wanted to add something that hasn't already been stated yet for anybody having the same issue.

You can use threading to create a new thread, which will receive data. After this, run your game loop normally in your main thread, and check for received data in each iteration. Received data should be placed inside a queue by the data receiver thread and read from that queue by the main thread.

#other imports
import queue
import threading

class MainGame:
    def __init__(self):
        #any code here
        self.data_queue = queue.Queue()
        data_receiver = threading.Thread(target=self.data_receiver)
        data_receiver.start()
        self.gameLoop()

    def gameLoop(self):
        while True:
            try:
                data = self.data_queue.get_nowait()
            except queue.Empty:
                pass

            self.gameIteration(data)

    def data_receiver(self):
         #Assuming self.sock exists
         data = self.sock.recv(1024).decode("utf-8")

         #edit the data in any way necessary here
         self.data_queue.put(data)

    def gameIteration(self, data):
        #Assume this method handles updating, drawing, etc
        pass

Note that this code is in Python 3.