基于Socket实现HTTP服务器时浏览器连接报错问题求助
Socket实现HTTP服务器报错WinError10053的解决办法
问题情况
用Socket手写HTTP服务器,之前运行正常,现在浏览器连接时触发如下错误,尝试删除部分代码、调整time.sleep()无效:
Traceback (most recent call last): File "C:/Users/Михаил Балошко/Downloads/dz/test_ekrana.py", line 16, in conn.sendall('Server : pythonsite/0.0.1 \n'.encode('UTF-8')) ConnectionAbortedError: [WinError 10053] 你的主机中的软件中止了一个已建立的连接
原代码
import socket import time s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('127.0.0.1', 5000)) s.listen(9000) conn, addr = s.accept() data = conn.recv(1024) print(f'Received: \n {data.decode()}') time.sleep(10) conn.sendall('HTTP/1.1 201 Created \n'.encode('UTF-8')) time.sleep(2) conn.sendall('Server : pythonsite/0.0.1 \n'.encode('UTF-8')) conn.sendall('Date: \n'.encode('UTF-8')) conn.sendall('Content-Type: application/octet-stream \n'.encode('UTF-8')) conn.sendall('Content-Length: 7 \n'.encode('UTF-8')) conn.sendall('Last-Modified: \n'.encode('UTF-8')) conn.sendall('Connection: keep-alive \n'.encode('UTF-8')) conn.sendall('Accept-Ranges: bytes \n'.encode('UTF-8')) conn.sendall('\n'.encode('UTF-8')) conn.sendall('\n'.encode('UTF-8')) conn.sendall('<html>\n'.encode('UTF-8')) conn.sendall('<head>\n'.encode('UTF-8')) conn.sendall('<title>pythonserv!</title>\n'.encode('UTF-8')) conn.sendall('</head>\n'.encode('UTF-8')) conn.sendall('<body>\n'.encode('UTF-8')) conn.sendall('<p>this is python web!!!</p>\n'.encode('UTF-8')) conn.sendall('</body>\n'.encode('UTF-8')) conn.sendall('</html>\n'.encode('UTF-8')) time.sleep(3) data = conn.recv(1024) time.sleep(8) print(f'Received: \n {data.decode()}') conn.close()
问题根源
- 浏览器超时断开:接收请求后
time.sleep(10)让服务器停顿10秒才发响应,浏览器默认等待响应的超时时间远短于10秒,会主动断开连接,导致后续发送数据时触发连接中止错误。 - HTTP响应格式不规范:
- 状态码用了
201 Created,但这里是返回网页内容,应该用200 OK; Content-Type设为application/octet-stream,但实际返回HTML,应该用text/html;Content-Length写的7,和实际HTML内容字节数严重不符;- HTTP协议要求响应头每行结尾用
\r\n(CRLF),而不是\n,响应头和正文之间只需要一个空行(\r\n\r\n);
- 状态码用了
- 多余的
recv操作:发送完响应后还尝试接收数据,此时浏览器可能已经关闭连接,会导致异常。
修复后的代码
import socket def main(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('127.0.0.1', 5000)) s.listen(5) # 监听队列设为合理值即可,不用9000 print("服务器启动,等待连接...") conn, addr = s.accept() print(f"来自 {addr} 的连接") # 接收请求数据 data = conn.recv(1024) print(f'Received: \n {data.decode()}') # 构造HTML正文 html_content = """<html> <head> <title>pythonserv!</title> </head> <body> <p>this is python web!!!</p> </body> </html>""" # 计算正文字节长度(UTF-8编码) content_length = len(html_content.encode('utf-8')) # 构造符合HTTP规范的响应头 response_headers = ( f"HTTP/1.1 200 OK\r\n" f"Server: pythonsite/0.0.1\r\n" f"Content-Type: text/html; charset=utf-8\r\n" f"Content-Length: {content_length}\r\n" f"Connection: close\r\n" # 告诉浏览器发送完响应后关闭连接 f"\r\n" # 响应头结束标记 ) # 发送响应头+正文 conn.sendall(response_headers.encode('utf-8')) conn.sendall(html_content.encode('utf-8')) # 关闭连接 conn.close() s.close() if __name__ == "__main__": main()
修复说明
- 移除了所有不必要的
time.sleep(),避免浏览器超时; - 修正了HTTP状态码、Content-Type、Content-Length等响应头;
- 严格按照HTTP协议用
\r\n分隔响应头,用\r\n\r\n分隔响应头和正文; - 设置
Connection: close,明确告知浏览器响应完成后关闭连接,避免后续不必要的接收操作; - 把代码整理成函数结构,更清晰易维护。
内容的提问来源于stack exchange,提问作者mihail989
相关产品推荐
相关产品推荐

