使用自签名证书的SSL Socket客户端与服务端连接断开如何解决?
问题原因
客户端的TCP连接与SSL握手执行顺序错误:
SSL/TLS握手需要基于已完成三次握手的TCP连接执行,你在客户端代码中先对未建立连接的原生socket做了SSL包装,再发起TCP连接,会导致握手逻辑提前触发,服务端收到非法握手报文后主动断开连接,触发10053报错。
修复方案
修正后的client.py
把connect和wrap_socket的顺序调换,先建立TCP连接再做SSL包装:
import ssl import socket server_addr = ('localhost', 8888) if __name__ == "__main__": ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client_socket: # 先建立TCP连接 client_socket.connect(server_addr) # 再对已连接的socket做SSL包装 ssl_socket = ctx.wrap_socket(client_socket) message = "Knock knock, our messages are encrypted with ssl" ssl_socket.send(message.encode()) ssl_socket.close()
可选优化:server.py增加调试提示
import ssl import socket cert_file = "cert.pem" # 包含私钥和证书 server_addr = ('localhost', 8888) if __name__ == "__main__": ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) ctx.load_cert_chain(cert_file) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket: server_socket.bind(server_addr) server_socket.listen(1) print("服务端已启动,等待客户端连接...") client_socket, _ = server_socket.accept() conn_stream = ctx.wrap_socket(client_socket, server_side=True) message = conn_stream.recv(1024) print(f'Client sent - "{message.decode()}"') conn_stream.close()
额外注意事项
如果修改顺序后仍报错,需要检查你的cert.pem是否合法,可通过openssl命令直接生成符合要求的自签名证书文件(同时包含私钥和证书):
openssl req -x509 -newkey rsa:4096 -keyout cert.pem -out cert.pem -days 365 -nodes
执行时所有提示项可直接回车跳过,生成的cert.pem放在代码同级目录即可。
测试流程
- 先生成合法的cert.pem文件
- 先运行server.py,看到等待连接提示后再运行client.py
- 服务端会打印收到的客户端消息,通信正常完成。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

