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

Python跨平台聊天程序Windows端报WinError 10038错误如何解决

问题背景

我正和一名学习Python的学生共同开发简单聊天程序,参考教程为:Simple Chat Room using Python

服务端部署(MacBook)

运行命令:
python server.py 0.0.0.0 6677
server.py代码如下:

# Python program to implement server side of chat room.
import socket
import select
import sys
from thread import *
 
"""The first argument AF_INET is the address domain of the
socket. This is used when we have an Internet Domain with
any two hosts The second argument is the type of socket.
SOCK_STREAM means that data or characters are read in
a continuous flow."""
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 
# checks whether sufficient arguments have been provided
if len(sys.argv) != 3:
    print ("Correct usage: script, IP address, port number")
    exit()
 
# takes the first argument from command prompt as IP address
IP_address = str(sys.argv[1])
 
# takes second argument from command prompt as port number
Port = int(sys.argv[2])
 
"""
binds the server to an entered IP address and at the
specified port number.
The client must be aware of these parameters
"""
server.bind((IP_address, Port))
 
"""
listens for 100 active connections. This number can be
increased as per convenience.
"""
server.listen(100)
 
list_of_clients = []
 
def clientthread(conn, addr):
 
    # sends a message to the client whose user object is conn
    conn.send("Welcome to this chatroom!")
 
    while True:
            try:
                message = conn.recv(2048)
                if message:
 
                    """prints the message and address of the
                    user who just sent the message on the server
                    terminal"""
                    print ("<" + addr[0] + "> " + message)
 
                    # Calls broadcast function to send message to all
                    message_to_send = "<" + addr[0] + "> " + message
                    broadcast(message_to_send, conn)
 
                else:
                    """message may have no content if the connection
                    is broken, in this case we remove the connection"""
                    remove(conn)
 
            except:
                continue
 
"""Using the below function, we broadcast the message to all
clients who's object is not the same as the one sending
the message """
def broadcast(message, connection):
    for clients in list_of_clients:
        if clients!=connection:
            try:
                clients.send(message)
            except:
                clients.close()
 
                # if the link is broken, we remove the client
                remove(clients)
 
"""The following function simply removes the object
from the list that was created at the beginning of
the program"""
def remove(connection):
    if connection in list_of_clients:
        list_of_clients.remove(connection)
 
while True:
 
    """Accepts a connection request and stores two parameters,
    conn which is a socket object for that user, and addr
    which contains the IP address of the client that just
    connected"""
    conn, addr = server.accept()
 
    """Maintains a list of clients for ease of broadcasting
    a message to all available people in the chatroom"""
    list_of_clients.append(conn)
 
    # prints the address of the user that just connected
    print (addr[0] + " connected")
 
    # creates and individual thread for every user
    # that connects
    start_new_thread(clientthread,(conn,addr))    
 
conn.close()
server.close()

客户端实现

本机(Mac)运行命令

python client.py 0.0.0.0 6677
client.py代码如下:

# Python program to implement client side of chat room.
import socket
import select
import sys
 
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if len(sys.argv) != 3:
    print ("Correct usage: script, IP address, port number")
    exit()
IP_address = str(sys.argv[1])
Port = int(sys.argv[2])
server.connect((IP_address, Port))
 
while True:
 
    # maintains a list of possible input streams
    sockets_list = [sys.stdin, server]
 
    """ There are two possible input situations. Either the
    user wants to give manual input to send to other people,
    or the server is sending a message to be printed on the
    screen. Select returns from sockets_list, the stream that
    is reader for input. So for example, if the server wants
    to send a message, then the if condition will hold true
    below.If the user wants to send a message, the else
    condition will evaluate as true"""
    read_sockets,write_socket, error_socket = select.select(sockets_list,[],[])
 
    for socks in read_sockets:
        if socks == server:
            message = socks.recv(2048)
            print (message)
        else:
            message = sys.stdin.readline()
            server.send(message)
            sys.stdout.write("<You>")
            sys.stdout.write(message)
            sys.stdout.flush()
server.close()

Windows 10 运行命令

python client.py 192.168.0.41 6677

问题现象

服务端可以看到Windows客户端已成功连接,但Windows端无法正常进入聊天室,报错[WinError 10038] an operation was attempted on something that is not a socket。Mac与Linux设备之间通信完全正常。

问题原因与排查方案

是否和Windows防火墙有关

存在该可能性。如果防火墙拦截了端口返程流量,会导致服务端发回的欢迎消息被拦截,客户端socket连接被强制断开,后续调用select操作已失效的socket就会触发该错误。

其他可能原因

  1. select函数跨平台兼容问题:Windows下的select函数不支持处理普通文件描述符,你代码里把sys.stdin(标准输入,属于文件描述符)和socket对象一起放进select监听列表,不符合Windows平台API要求,这是最核心的问题。
  2. 编码兼容问题:不同平台默认编码不同,send/recv没有显式编解码,可能导致传输异常触发连接断开。
  3. Python版本差异:你参考的教程是Python2版本的代码,Windows如果装的是Python3,部分socket API调用逻辑会有差异,也会导致socket失效。

排查解决步骤

  • 先验证网络连通性:在Windows上用Test-NetConnection命令测试6677端口连通性
    Test-NetConnection 192.168.0.41 -Port 6677
    
    如果连通失败,先临时关闭Mac的防火墙和Windows的防火墙,再测试确认是否是防火墙拦截。
  • 修复客户端代码的select兼容问题:Windows下不能把stdin放进select监听列表,改为开单独线程处理标准输入,主线程只负责监听服务端消息,子线程循环读取用户输入并发送给服务端。
  • 统一编解码:所有send操作前把字符串编码为utf-8,recv后解码为utf-8,适配不同平台编码差异。
  • 统一Python版本:确认所有设备运行的Python版本一致,推荐升级到Python3,对应修改Python2的旧语法(比如thread模块改名为_thread,调整print语法等)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 01:06:05