HTTP代理服务器停止接收请求后无法自动关闭的问题求助
嘿,我仔细看了你的HTTP代理代码,发现几个导致程序无法自动退出的关键问题,咱们一个个来解决:
核心问题分析
- 主线程无限阻塞在
accept():你的主循环是while 1的无限循环,会一直卡在s.accept()等待新连接——哪怕所有客户端都断开了,主线程还是会蹲在这里等新请求,自然不会自动退出。 - 未处理客户端提前断开的情况:如果浏览器突然断开连接,
conn.recv()会返回空字节,但你的代码里没判断这种情况,可能导致线程异常或者一直挂着。 - 字符串分割的小bug:
request.split('n')[0]少了反斜杠,应该是'\n',不然没法正确拆分HTTP请求的第一行。
解决方案与修改后的代码
我给你调整了代码,解决这些问题:
from socket import * from _thread import * MAX_DATA_RECV = 4096 # max number of bytes we receive at once running = True # 全局运行标志,用于控制主循环 active_threads = 0 # 跟踪活跃线程数 def start(port_5, my_port): global running, active_threads s = socket(AF_INET, SOCK_STREAM) s.settimeout(5) # 设置accept超时,每5秒检查一次是否需要退出 s.bind(('', my_port)) s.listen(1) while running: try: conn, client_addr = s.accept() active_threads += 1 # 启动处理线程,主线程退出时子线程会自动终止 start_new_thread(proxy_thread, (conn, client_addr)) except KeyboardInterrupt: print('\nProgram closed. Interrupted by the user') running = False except timeout: # 超时后检查是否还有活跃线程,没有就退出 if active_threads == 0: print("No active connections, exiting...") running = False s.close() print("Proxy server stopped successfully") def proxy_thread(conn, client_addr): global active_threads try: # 获取浏览器的请求,先判断是否为空(客户端断开) request = conn.recv(MAX_DATA_RECV).decode('utf-8') if not request: print(f"Client {client_addr} disconnected") return # 修复换行符分割的bug first_line = request.split('\n')[0] # 解析URL url = first_line.split(' ')[1] # 以下是原有的URL解析逻辑,保持不变 http_pos = url.find("://") if http_pos == -1: temp = url else: temp = url[(http_pos+3):] port_pos = temp.find(":") webserver_pos = temp.find("/") if webserver_pos == -1: webserver_pos = len(temp) webserver = "" port = -1 if (port_pos == -1 or webserver_pos < port_pos): port = 80 webserver = temp[:webserver_pos] else: port = int((temp[(port_pos+1):])[:webserver_pos-port_pos-1]) webserver = temp[:port_pos] print(f"Connect to: {webserver}:{port}") # 连接目标服务器并转发请求 s = socket(AF_INET, SOCK_STREAM) s.connect((webserver, port)) s.send(request.encode()) # 接收目标服务器的响应并转发给客户端 while True: data = s.recv(MAX_DATA_RECV) if len(data) > 0: conn.send(data) else: break s.close() except Exception as e: print(f"Error in thread: {e}") finally: conn.close() active_threads -= 1 # 线程结束后减少活跃计数
关键修改点说明
- 添加超时与活跃线程跟踪:给监听socket设置5秒超时,每次超时后检查是否还有活跃连接,没有就自动退出主循环。
- 处理客户端空请求:在
proxy_thread开头判断request是否为空,及时关闭连接并结束线程,避免无效线程占用资源。 - 修复换行符bug:把
'n'改成'\n',确保正确拆分HTTP请求行。 - 线程资源清理:用
finally块保证无论线程是否异常,都会关闭客户端连接并更新活跃线程计数。
这样修改后,当你停止发送请求(所有客户端断开),等待5秒后程序就会自动退出;按Ctrl+C也能正常终止。
内容的提问来源于stack exchange,提问作者Dark_John
相关产品推荐
相关产品推荐

