如何修正Python HTTPS服务器代码中的运行报错问题?
HTTPS服务器报错原因及解决方案
问题描述
生成HTTPS密钥的命令
openssl req -x509 -newkey rsa:2048 -keyout privkey.pem -out cert.pem -days 365
报错的Python服务器代码(simple-https-server.py)
from http.server import HTTPServer, BaseHTTPRequestHandler import ssl httpd = HTTPServer(('localhost', 4446), BaseHTTPRequestHandler) httpd.socket = ssl.wrap_socket (httpd.socket, keyfile="privkey.pem", certfile='cert.pem', server_side=True) httpd.serve_forever()
执行报错信息
Traceback (most recent call last): File "/usr/lib/python3.9/ssl.py", line 1020, in _create self.getpeername() OSError: [Errno 128] Transport endpoint is not connected During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/cemfa/programs/html/gaming/backup/html/simple-https-server.py", line 7, in <module> httpd.socket = ssl.wrap_socket (httpd.socket, File "/usr/lib/python3.9/ssl.py", line 1439, in wrap_socket return context.wrap_socket( File "/usr/lib/python3.9/ssl.py", line 501, in wrap_socket return self.sslsocket_class._create( File "/usr/lib/python3.9/ssl.py", line 1032, in _create notconn_pre_handshake_data = self.recv(1) File "/usr/lib/python3.9/ssl.py", line 1262, in recv return super().recv(buflen, flags) BlockingIOError: [Errno 11] Resource temporarily unavailable
用户疑问:
- 该报错产生的原因是什么?
- 为何代码在Windows Python环境下可正常运行,但在Cygwin(Linux模拟器)中运行失败?
原因分析
核心报错原因
你错误地对监听套接字直接调用了ssl.wrap_socket()。HTTPServer初始化后的socket是用于监听客户端连接的套接字,而非已建立的客户端连接套接字。ssl.wrap_socket()需要在已完成三次握手的客户端连接上执行SSL握手,直接包装监听套接字时,SSL层会尝试读取数据触发握手,但此时没有任何客户端连接,就会抛出"Transport endpoint is not connected"错误,后续进一步触发阻塞IO异常。
Cygwin与Windows的差异原因
- Windows平台的Python网络实现对这种错误用法做了兼容处理,允许直接包装监听套接字并正常工作;
- Cygwin遵循Linux的网络套接字规范,严格要求SSL包装操作必须在已建立的客户端连接套接字上执行,因此会触发错误。你提到的"低级网络操作权限"不是本次问题的核心原因(你使用的4446端口大于1024,无需管理员权限)。
修正后的代码
方案1:在请求处理器中包装连接套接字
重写BaseHTTPRequestHandler的setup方法,在每次接受客户端连接后再进行SSL包装:
from http.server import HTTPServer, BaseHTTPRequestHandler import ssl class SSLRequestHandler(BaseHTTPRequestHandler): def setup(self): # 对已建立的客户端连接进行SSL包装 self.connection = ssl.wrap_socket( self.connection, keyfile="privkey.pem", certfile='cert.pem', server_side=True ) super().setup() httpd = HTTPServer(('localhost', 4446), SSLRequestHandler) httpd.serve_forever()
方案2:使用SSLContext(推荐,Python 3.7+)
通过ssl.SSLContext创建并配置SSL上下文,再包装监听套接字,这种方式更符合现代Python SSL最佳实践:
from http.server import HTTPServer, BaseHTTPRequestHandler import ssl # 创建TLS服务器上下文并加载证书密钥 context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) context.load_cert_chain(certfile='cert.pem', keyfile='privkey.pem') httpd = HTTPServer(('localhost', 4446), BaseHTTPRequestHandler) # 用上下文包装监听套接字 httpd.socket = context.wrap_socket(httpd.socket, server_side=True) httpd.serve_forever()
内容的提问来源于stack exchange,提问作者Acknowledge
相关产品推荐
相关产品推荐

