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

OSError: [WinError 10022]参数无效问题排查(P2P文件分发系统)

问题描述

实现了一套以服务器为中间人的P2P文件分发系统,用于向N个客户端分发文件。服务器端执行connect操作时触发OSError: [WinError 10022] An invalid argument was supplied错误,客户端TCP处理逻辑仅显示N个端口超时,请求排查问题原因。

服务器端出错代码片段

try:
        for i in l:
            print(i)
            x = random.randint(0,N-1)
            print(x,"Index")
            serverSocketTCPRequest = serverSocketTCPList[x]
            serverSocketTCPRequest.settimeout(2)
            serverSocketTCPRequest.connect((i[0],i[1]))
            serverSocketTCPRequest.send("SEND".encode())
            serverSocketTCPRequest.send(str(chunkID).encode())
            data = serverSocketTCPRequest.recv(1024)
            serverSocketTCPRequest.close()
            b = False
            return data
    except Exception as ex:
        print(traceback.format_exc())                
        time.sleep(1)
        # print(l)
        pass

报错栈信息

Traceback (most recent call last):
  File "d:\IITD\5th Sem\COL334\Assignment 2\server.py", line 149, in getChunks
    serverSocketTCPRequest.connect((i[0],i[1]))
OSError: [WinError 10022] An invalid argument was supplied
Traceback (most recent call last):

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "d:\IITD\5th Sem\COL334\Assignment 2\server.py", line 198, in sendChunkRequest
    checkMessage, serverAddress = serverSocketUDPRequest.recvfrom(1024)
socket.timeout: timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "d:\IITD\5th Sem\COL334\Assignment 2\server.py", line 149, in getChunks
    serverSocketTCPRequest.connect((i[0],i[1]))
OSError: [WinError 10022] An invalid argument was supplied

客户端TCP处理代码片段

def handleTCP(client:Client):
global N
while(True):
    try:
        # print(clientList.index(client), client.clientSocketTCPRequest.getsockname())
        client.clientSocketTCPRequest.listen(2*N)
        client.clientSocketTCPRequest.settimeout(2)
        connectionSocket, addr = client.clientSocketTCPRequest.accept()
        print("Connected")
        message = connectionSocket.recv(1024).decode()
        if message.decode() == "SEND":
            i = connectionSocket.recv(1024).decode()
            connectionSocket.send(client.dict[int(i)])
            connectionSocket.close()
        elif message.decode() == "GET":
            i = connectionSocket.recv(1024).decode()
            client.dict[int(i)] = connectionSocket.recv(1024)
            connectionSocket.close()
    except Exception as ex:
        template = "An exception of type {0} occurred. Arguments:\n{1!r}"
        m = template.format(type(ex).__name__, ex.args)
        print(m,client.clientSocketTCPRequest.getsockname())
        # print(traceback.format_exc())
        continue

说明:存在完整的client.py、server.py代码及测试文件A2_small_file.txt。

问题排查与修复方案

核心问题分析

  1. 服务器端socket复用错误:
    服务器从serverSocketTCPList中随机取出socket使用,用完后调用close()关闭,但该socket仍留在列表中。后续再次取到这个已关闭的socket执行connect时,会触发WinError 10022错误——已关闭的socket对象无法再用于连接操作,参数无效。
  2. 客户端TCP处理逻辑错误:
    • 对recv得到的字符串重复调用decode():message = connectionSocket.recv(1024).decode()已经完成解码,后续message.decode()会直接抛出异常,导致客户端无法正确处理服务器的请求,进而服务器端出现超时。
    • 循环内重复调用listen():listen()只需在socket绑定后调用一次,每次循环都调用会导致socket状态异常,引发超时。

具体修复步骤

服务器端修复

放弃复用旧socket,每次需要连接时创建新的socket实例:

try:
        for i in l:
            print(i)
            # 创建新的TCP socket
            serverSocketTCPRequest = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            serverSocketTCPRequest.settimeout(2)
            serverSocketTCPRequest.connect((i[0],i[1]))
            serverSocketTCPRequest.send("SEND".encode())
            serverSocketTCPRequest.send(str(chunkID).encode())
            data = serverSocketTCPRequest.recv(1024)
            serverSocketTCPRequest.close()
            b = False
            return data
    except Exception as ex:
        print(traceback.format_exc())                
        time.sleep(1)
        pass

也可维护一个动态的可用socket列表,关闭socket后从列表中移除,避免重复使用已失效的socket。

客户端修复

  1. 移除重复的decode()调用:
message = connectionSocket.recv(1024).decode()
if message == "SEND":  # 去掉多余的decode()
  1. 将listen()移到while循环外部,仅调用一次:
def handleTCP(client:Client):
global N
# 只调用一次listen
client.clientSocketTCPRequest.listen(2*N)
while(True):
    try:
        client.clientSocketTCPRequest.settimeout(2)
        connectionSocket, addr = client.clientSocketTCPRequest.accept()
        print("Connected")
        message = connectionSocket.recv(1024).decode()
        if message == "SEND":
            i = connectionSocket.recv(1024).decode()
            connectionSocket.send(client.dict[int(i)])
            connectionSocket.close()
        elif message == "GET":
            i = connectionSocket.recv(1024).decode()
            client.dict[int(i)] = connectionSocket.recv(1024)
            connectionSocket.close()
    except Exception as ex:
        template = "An exception of type {0} occurred. Arguments:\n{1!r}"
        m = template.format(type(ex).__name__, ex.args)
        print(m,client.clientSocketTCPRequest.getsockname())
        continue
  1. 可选优化:处理recv的不完整数据,添加循环确保接收到完整的指令字符串。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 20:35:23