如何无需重启服务器即可自动重启崩溃的Python Socket服务
问题根因
- 代码未对socket通信异常做捕获处理:客户端意外断开时,
recv()、send()方法会直接抛出ConnectionResetError、BrokenPipeError等异常,未捕获的异常会直接终止对应线程,严重时会导致整个服务进程退出 - 未设置端口复用标识:服务意外退出后,端口会处于TIME_WAIT状态,短时间内重新启动socket服务会绑定端口失败,所以会出现必须重启整台服务器才能恢复的问题
- 当前用crontab仅做开机启动,没有进程存活监控和异常自动恢复能力
代码修复方案
直接替换原有代码即可,修复点包括异常捕获、端口复用、异常断开时的资源自动清理:
import socket from sys import prefix from threading import Thread def accept_incoming_connections(): while True: try: client, client_address = SERVER.accept() print("%s:%s has connected." % client_address) client.send(bytes("you have been connected", "utf8")) addresses[client] = client_address Thread(target=handle_client, args=(client,)).start() except Exception as e: print(f"连接接受异常: {e}") continue def handle_client(client): name = "" try: name = client.recv(BUFSIZE).decode("utf8") clients[client] = name while True: msg = client.recv(BUFSIZE) # 客户端意外断开时recv会返回空字节,需额外判断 if not msg: break if msg != bytes("{quit}", "utf8"): prefix = name + ": " broadcast(msg, prefix) else: client.send(bytes("{quit}", "utf8")) break except Exception as e: print(f"客户端{name if name else addresses.get(client, '未知')}通信异常: {e}") finally: # 无论正常退出还是异常退出都统一清理资源 try: client.close() except: pass if client in clients: del clients[client] if client in addresses: del addresses[client] print(f"客户端{name if name else addresses.get(client, '未知')}已断开连接") def broadcast(msg, prefix=""): # 广播添加异常捕获,避免单个客户端断开导致全量广播失败 remove_socks = [] for sock in clients: try: sock.send(bytes(prefix, "utf8")+msg) except: remove_socks.append(sock) # 批量清理异常客户端连接 for sock in remove_socks: try: sock.close() except: pass del clients[sock] if sock in addresses: del addresses[sock] addresses = {} clients = {} HOST = "替换为你的服务器实际IP" PORT = 替换为你的服务端口号 # 注意这里要为整数格式,不要包裹引号 BUFSIZE = 1024 ADDR = (HOST, PORT) SERVER = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 开启端口复用,服务重启时无需等待端口释放 SERVER.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) SERVER.bind(ADDR) if __name__ == "__main__": SERVER.listen(5) print("Waiting for connection...") ACCEPT_THREAD = Thread(target=accept_incoming_connections, daemon=True) ACCEPT_THREAD.start() try: ACCEPT_THREAD.join() except KeyboardInterrupt: print("服务正在关闭") finally: SERVER.close()
无需重启服务器的服务管理方案
替换crontab开机启动的方式,改用systemd管理该socket服务,配置完成后可实现:
- 服务异常崩溃自动重启
- 手动重启服务只需执行
systemctl restart socket-chat.service,不需要重启整台服务器 - 可随时查看服务运行日志排查问题
systemd配置步骤
- 新建配置文件
/etc/systemd/system/socket-chat.service,内容如下:
[Unit] Description=Socket Chat Service After=network.target [Service] Type=simple # 下方路径替换为你的Python解释器实际路径和代码文件实际存放路径 ExecStart=/usr/bin/python3 /opt/chat/server.py Restart=always RestartSec=3 User=root [Install] WantedBy=multi-user.target
- 执行以下命令生效配置即可:
systemctl daemon-reload systemctl enable socket-chat.service systemctl start socket-chat.service
内容的提问来源于stack exchange,提问作者RobinM
相关产品推荐
相关产品推荐

