Python2中在不同线程运行HTTP与HTTPS服务器问题
解决Python2.7多线程运行HTTP/HTTPS服务器的异常问题
嘿,我一眼就看出你代码里的问题啦——你在创建线程的时候犯了一个很常见的错误:你直接调用了httpd.serve_forever(),而不是把这个函数的引用传给线程。
问题根源
start_new_thread的第一个参数需要是函数对象,但你现在写的start_new_thread(httpd.serve_forever())会立刻执行serve_forever()方法,这会让主线程直接卡在第一个HTTP服务器的无限循环里,根本没机会启动第二个HTTPS线程。而且因为主线程被阻塞了,后面的except KeyboardInterrupt也根本不会触发,自然没法正常关闭服务器。
修复步骤
- 正确传递线程函数:把
serve_forever作为函数引用传递,而不是调用它,参数用空元组()表示没有额外参数。 - 优雅关闭服务器:捕获到
KeyboardInterrupt时,调用两个服务器的shutdown()方法来终止serve_forever()的循环,然后等待线程结束。 - 推荐用更安全的
threading模块:Python2.7的thread模块(start_new_thread属于它)比较底层,threading模块的Thread类更易用且线程管理更安全。
完整修正代码示例
import BaseHTTPServer import ssl from threading import Thread # 定义你的请求处理器(这里用默认的示例处理器) class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.end_headers() self.wfile.write("Hello from HTTP server!\n") class SimpleHTTPSRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.end_headers() self.wfile.write("Hello from HTTPS server!\n") if __name__ == "__main__": # 初始化HTTP服务器 httpd = BaseHTTPServer.HTTPServer(('0.0.0.0', 3000), SimpleHTTPRequestHandler) # 初始化HTTPS服务器(使用自签名证书) httpsd = BaseHTTPServer.HTTPServer(('0.0.0.0', 3001), SimpleHTTPSRequestHandler) httpsd.socket = ssl.wrap_socket( httpsd.socket, server_side=True, certfile='server.crt', # 你的自签名证书文件 keyfile='server.key', # 你的私钥文件 ssl_version=ssl.PROTOCOL_TLSv1_2 ) # 创建线程,注意这里传递的是函数对象,不是调用结果 http_thread = Thread(target=httpd.serve_forever) https_thread = Thread(target=httpsd.serve_forever) # 设置线程为守护线程(可选,但主线程退出时会自动终止) http_thread.daemon = True https_thread.daemon = True # 启动线程 http_thread.start() https_thread.start() print("HTTP server running on port 3000, HTTPS on 3001. Press Ctrl+C to stop.") try: # 主线程保持运行,等待用户中断 while True: pass except KeyboardInterrupt: print("\nClosing the service...") # 关闭服务器 httpd.shutdown() httpsd.shutdown() # 等待线程结束 http_thread.join() https_thread.join() print("Services closed successfully.")
额外说明
- 确保你已经生成了自签名证书:可以用OpenSSL命令生成:
openssl req -new -x509 -keyout server.key -out server.crt -days 365 -nodes - 用
threading.Thread代替start_new_thread的好处是可以更方便地管理线程,比如调用join()等待线程结束,设置守护线程等。 - 主线程里的
while True: pass是为了让主线程保持活跃,直到用户按下Ctrl+C,这样才能捕获到中断信号。
内容的提问来源于stack exchange,提问作者x y
相关产品推荐
相关产品推荐

