Python套接字如何防止recv函数挂起?

18

我正在尝试使用sockets在pygame中创建一个双人游戏,问题是,当我尝试在这一行接收数据时:

message = self.conn.recv(1024)

Python会一直等待直到接收到数据。这样做的问题是,当客户端没有通过套接字发送任何数据时,它会暂停游戏循环并导致黑屏。 我该如何防止recv这样做?

提前感谢。


2
使用多个线程或异步IO。 - JBernardo
3个回答

27

使用非阻塞模式。(参见socket.setblocking。)

或在调用 recv 前检查是否有可用数据。 例如,使用select.select:

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

3
您可以使用signal模块来停止挂起的recv线程。
在recv线程中:
try:
    data = sock.recv(1024)
except KeyboardInterrupt:
    pass

在解释线程中:
signal.pthread_kill(your_recving_thread.ident, signal.SIGINT)

4
你需要在回答中更加清晰明确。 - Elio Lako

3

我知道这是一篇旧文章,但由于我最近也在类似的项目上工作,所以我想为任何遇到同样问题的人添加尚未被提出的内容。

您可以使用线程创建一个新线程,该线程将接收数据。之后,在主线程中正常运行游戏循环,并在每次迭代中检查接收到的数据。接收到的数据应该由数据接收线程放入队列中,并由主线程从该队列中读取。

#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

请注意,此代码适用于Python 3版本。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接