Python Socket - 处理客户端断开连接

3 投票
2 回答
8095 浏览
提问于 2025-04-28 09:00

我对在Python中使用Sockets类进行了很多研究,但还是很难理解如何解决我的问题。让我先说明一下,我对Python完全没有经验。我拼凑的代码是从其他几个例子中来的。大体上是能工作的,只是还有一个最后的小bug需要解决。

这个脚本的目的是在树莓派上运行,树莓派的唯一功能就是这个。通过TCP,你可以请求一个图片编号,然后树莓派会全屏显示那张图片。听起来简单吧?

不过,问题是,当与客户端的以太网连接断开,或者客户端关闭连接时,脚本就会进入一个糟糕的无限循环,CPU使用率飙升,我只能强制重启树莓派。我需要找到一种方法,确保这种情况不会发生,并且让客户端在断开连接或网络出现问题时能够重新连接到这个服务器。

这是我目前的进展。

import sys
import pygame
import SocketServer

pygame.init()
screen = pygame.display.set_mode((0,0), pygame.FULLSCREEN, 0)
pygame.mouse.set_visible(False)
imagesequence = []
imagesequence.append(pygame.image.load("/home/pi/appfiles/image1.png")
imagesequence.append(pygame.image.load("/home/pi/appfiles/image2.png")

screensaver = []
screensaver.append(pygame.image.load("/home/pi/appfiles/screensaver1.png")

class MyTCPHandler(SocketServer.StreamRequestHandler):
    def handle(self):
        while True:
            self.data = self.rfile.readline().strip()

            isNum = False

            try:
                int(self.data)
                isNum = True
            except ValueError:
                isNum = False

            if isNum:
                framenumber = int(self.data)
                if framenumber >= 1 and framenumber <= len(imagesequence):
                    screen.blit(imagesequence[framenumber-1], (0,0))
                    pygame.display.flip()
                elif framenumber >= 901 and framenumber <= 900+len(screensaver):
                    screen.blit(screensaver[framenumber-901], (0,0))
                    pygame.display.flip()
            else:
                if self.data == "q":
                    pygame.quit()
                    server.shutdown()

if __name__ == "__main__":
    HOST, PORT = "192.168.1.51", 5050

    SocketServer.TCPServer.allow_reuse_address = True
    server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)

    server.serve_forever()

通过TCP连接退出脚本也不行,但我对此不是太担心。毕竟,最终这个脚本是不会有理由退出的。

暂无标签

2 个回答

0

经过不断地查找代码,我还是无法回答第一个问题。看起来在这么高的层次上,你无法检测到一个套接字(socket)关闭的情况。你可以看看asyncore和asynchat这两个模块,虽然现在可能不太流行,但它们还是可以用的。

至于第二个问题,你需要在接收到一个'q'的时候跳出循环。

开个玩笑的代码示例:

break
2

self.rfile.readline() 在套接字连接关闭时会返回一个空字符串 ''。不过,在使用 .strip() 之前一定要检查一下,因为如果发送的是只有空格的行,经过 .strip() 处理后也会变成空字符串。

import socketserver

class MyTCPHandler(SocketServer.StreamRequestHandler):
    def handle(self):
        while True:
            self.data = self.rfile.readline()
            if not self.data:
                break
            self.data = self.data.strip()
            ...

撰写回答