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

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  # 线程结束后减少活跃计数

关键修改点说明

  1. 添加超时与活跃线程跟踪:给监听socket设置5秒超时,每次超时后检查是否还有活跃连接,没有就自动退出主循环。
  2. 处理客户端空请求:在proxy_thread开头判断request是否为空,及时关闭连接并结束线程,避免无效线程占用资源。
  3. 修复换行符bug:把'n'改成'\n',确保正确拆分HTTP请求行。
  4. 线程资源清理:用finally块保证无论线程是否异常,都会关闭客户端连接并更新活跃线程计数。

这样修改后,当你停止发送请求(所有客户端断开),等待5秒后程序就会自动退出;按Ctrl+C也能正常终止。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:35:40