Python多线程Socket服务器调用accept()后直接退出问题求助
Python多线程Socket服务器启动后直接退出问题分析
问题描述
我近期正在学习Python的Socket编程,尤其是多线程Socket服务器开发。我的服务器代码如下:
import socket import threading class Server(object): def __init__(self): self.g_conn_pool = {} self.num = 0 self.address = ('', 8022) self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.server_socket.bind(self.address) self.server_socket.listen(128) def accept_client(self): print("accept_client\n") while True: print('in') client_socket, info = self.server_socket.accept() print('client name: ' + client_socket.getsockname()) print(client_socket, info) thread = threading.Thread(target=self.recv_msg, args=(client_socket, info)) thread.daemon = True thread.start() def recv_msg(self, client, info) pass def start_new_thread(self): thread = threading.Thread(target=self.accept_client, args=()) thread.daemon = True thread.start() print("start_new_thread") multi_server = Server() multi_server.start_new_thread()
运行该程序时,发现程序总是在执行client_socket, info = self.server_socket.accept()这一行后直接退出,'client name: '相关内容并未打印。我原本预期服务器启动后会持续等待客户端连接,但还没来得及启动客户端程序,服务器就已快速退出。请问该问题由什么原因导致?是否缺少相关代码或操作?
问题原因
守护线程特性导致主程序提前退出
你将监听客户端连接的accept_client线程设置为daemon=True,Python的规则是:当所有非守护线程(包括主线程)执行完毕后,程序会立即终止,所有守护线程会被强制停止。你的主程序在执行完multi_server.start_new_thread()后没有任何阻塞逻辑,主线程直接结束,导致作为守护线程的accept_client还没进入accept()的阻塞等待就被终止了。存在语法错误
recv_msg方法的定义末尾缺少冒号:,这会触发语法错误,虽然你描述程序是直接退出,但这个错误必须先修复才能保证程序正常运行。
解决方案
1. 修复语法错误
给recv_msg方法的定义添加冒号:
def recv_msg(self, client, info): pass
2. 阻止主线程提前退出
有两种常见方式可以让主线程保持运行,从而让监听线程正常工作:
方式一:使用输入阻塞
在主程序的最后添加input()语句,让主线程等待用户输入才会结束:
multi_server = Server() multi_server.start_new_thread() input("服务器已启动,按回车键退出...\n")
方式二:将监听线程设为非守护线程并让主线程等待
修改start_new_thread方法,去掉守护线程的设置,并返回线程对象,然后让主线程等待该线程结束:
def start_new_thread(self): thread = threading.Thread(target=self.accept_client, args=()) thread.start() print("start_new_thread") return thread # 主程序部分 multi_server = Server() server_thread = multi_server.start_new_thread() server_thread.join()
内容的提问来源于stack exchange,提问作者yamato
相关产品推荐
相关产品推荐

