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

添加SSL认证时遇WinError 10038:非套接字操作问题排查

SSL认证TCP服务器报错WinError 10038的原因与修复

问题背景

我创建了一个可显示客户端发送数据的TCP服务器,原本运行正常,但添加SSL认证后出现故障,调用wrap_socket()函数时抛出错误。

服务器代码

import socket
import json
import ssl 

HOST: str = '127.0.0.1'
PORT: int = 5507

def create_server_socket() -> socket.socket:
    """Creates a TCP socket, binds it to the host and port and listens for a connection. Will try again should the process fail"""
    try:
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_socket.bind((HOST, PORT))
        server_socket.listen()

        print(f"SERVER LISTENING ON {HOST, PORT}")
        return server_socket
    except socket.error as message:
        print("Socket creation error: " + str(message) + "\n Retrying...")
        return create_server_socket()

def main() -> None:
    """Main function to start the server."""
    context : ssl.SSLContext = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)    
    context.load_cert_chain("ssl/server.crt", "ssl/server.key")
    server_socket: socket.socket = create_server_socket()

    context.wrap_socket(server_socket, server_side=True)

    client_socket, client_address = server_socket.accept()
    with client_socket:
        data: bytes = client_socket.recv(1024)
        print(f"{client_address} connected as {data.decode(encoding='utf-8')}\n")
        while True:
            data: bytes = client_socket.recv(1024)
            decoded_data: str = data.decode(encoding='utf-8')
            try:
                data: dict =json.loads(decoded_data)
            except json.JSONDecodeError:
                print(f"{client_address} disconnected!")
                server_socket.close()
                client_socket.close()
                break
            print(f"{data['sender']}: {data['msg']}")
            

if __name__ == '__main__':
    main()

错误信息

Traceback (most recent call last):
  File "c:\Users\Yoocee\Desktop\Algorithmic Sciences\server.py", line 82, in <module>
    main()
  File "c:\Users\Yoocee\Desktop\Algorithmic Sciences\server.py", line 57, in main
    client_socket, client_address = server_socket.accept()
                                    ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Yoocee\AppData\Local\Programs\Python\Python311\Lib\socket.py", line 294, in accept
    fd, addr = self._accept()
               ^^^^^^^^^^^^^^
OSError: [WinError 10038] An operation was attempted on something that is not a socket

错误原因

问题出在wrap_socket()的使用逻辑上:
当调用context.wrap_socket(server_socket, server_side=True)时,该函数不会修改原有TCP套接字,而是返回一个新的SSL套接字对象,同时原server_socket会被自动关闭(默认do_handshake_on_connect=True,包装过程中原套接字的文件描述符会被接管)。后续继续使用已失效的原套接字调用accept(),就会触发"操作对象不是套接字"的错误。

修复方法

将wrap_socket()返回的SSL套接字赋值给server_socket变量,后续所有监听、接受连接的操作都使用这个新的SSL套接字:

修改main函数中的关键代码:

# 原错误代码
context.wrap_socket(server_socket, server_side=True)

# 修改后正确代码
server_socket = context.wrap_socket(server_socket, server_side=True)

完整修复后的main函数

def main() -> None:
    """Main function to start the server."""
    context : ssl.SSLContext = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)    
    context.load_cert_chain("ssl/server.crt", "ssl/server.key")
    server_socket: socket.socket = create_server_socket()

    # 关键修复:将wrap_socket返回的SSL套接字赋值给原变量
    server_socket = context.wrap_socket(server_socket, server_side=True)

    client_socket, client_address = server_socket.accept()
    with client_socket:
        data: bytes = client_socket.recv(1024)
        print(f"{client_address} connected as {data.decode(encoding='utf-8')}\n")
        while True:
            data: bytes = client_socket.recv(1024)
            decoded_data: str = data.decode(encoding='utf-8')
            try:
                data: dict =json.loads(decoded_data)
            except json.JSONDecodeError:
                print(f"{client_address} disconnected!")
                server_socket.close()
                client_socket.close()
                break
            print(f"{data['sender']}: {data['msg']}")

额外注意:客户端也需要使用SSL方式连接,否则会握手失败。客户端需用ssl.wrap_socket或context.wrap_socket包装自身套接字,必要时指定server_hostname参数验证服务器证书。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:20:56