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就会触发该错误。
其他可能原因
- select函数跨平台兼容问题:Windows下的select函数不支持处理普通文件描述符,你代码里把
sys.stdin(标准输入,属于文件描述符)和socket对象一起放进select监听列表,不符合Windows平台API要求,这是最核心的问题。 - 编码兼容问题:不同平台默认编码不同,send/recv没有显式编解码,可能导致传输异常触发连接断开。
- Python版本差异:你参考的教程是Python2版本的代码,Windows如果装的是Python3,部分socket API调用逻辑会有差异,也会导致socket失效。
排查解决步骤
- 先验证网络连通性:在Windows上用Test-NetConnection命令测试6677端口连通性
如果连通失败,先临时关闭Mac的防火墙和Windows的防火墙,再测试确认是否是防火墙拦截。Test-NetConnection 192.168.0.41 -Port 6677 - 修复客户端代码的select兼容问题:Windows下不能把stdin放进select监听列表,改为开单独线程处理标准输入,主线程只负责监听服务端消息,子线程循环读取用户输入并发送给服务端。
- 统一编解码:所有send操作前把字符串编码为utf-8,recv后解码为utf-8,适配不同平台编码差异。
- 统一Python版本:确认所有设备运行的Python版本一致,推荐升级到Python3,对应修改Python2的旧语法(比如thread模块改名为_thread,调整print语法等)。
内容的提问来源于stack exchange,提问作者apg
相关产品推荐
相关产品推荐

