You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无需重启服务器即可自动重启崩溃的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配置步骤

  1. 新建配置文件 /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
  1. 执行以下命令生效配置即可:
systemctl daemon-reload
systemctl enable socket-chat.service
systemctl start socket-chat.service

内容的提问来源于stack exchange,提问作者RobinM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 10:06:04