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

如何修复Raspberry Pi 4上asyncio客户端报[Win 10022]错误?

错误原因及修复方案

让我来帮你分析这个错误并修复代码:

核心错误原因

你遇到的OSError: [WinError 10022] An invalid argument was supplied是由两个关键问题导致的:

  1. 未连接的非阻塞Socket调用getsockname():你在Socket还未完成连接时就调用getsockname(),此时Socket还没有绑定到本地地址,系统无法返回有效信息,因此抛出无效参数错误。
  2. 混用同步Socket和asyncio异步模型:直接调用self.s.connect(addr)在非阻塞模式下会立刻抛出BlockingIOError,因为非阻塞Socket不会等待连接完成,而你没有用asyncio的机制来处理异步连接流程,完全违背了asyncio的异步编程逻辑。

修复后的完整代码

aserver/init.py

import asyncio
class Client:
    def __init__(self):
        self.reader = None
        self.writer = None

    async def connect(self, addr):
        # 使用asyncio官方推荐的流API建立异步连接
        self.reader, self.writer = await asyncio.open_connection(addr[0], addr[1])
        # 连接建立后再获取本地地址,此时是安全有效的
        local_addr = self.writer.get_extra_info('sockname')
        print(f"Connecting as {local_addr}")

    async def recv(self, buf_size):
        # 异步读取数据,符合asyncio模型
        data = await self.reader.read(buf_size)
        if data:
            print(f"Received {data.decode()} in byte data")
        return data

    async def close_conn(self):
        print("Closed connection with server")
        if self.writer:
            self.writer.close()
            await self.writer.wait_closed()  # 等待连接完全关闭,避免资源泄漏

    async def send_bytes(self, data: bytes):
        self.writer.write(data)
        await self.writer.drain()  # 异步等待数据发送完成
        print(f"Sent {data.decode()} in byte format")

class Server:
    """Implement handle function or decorate a function with @Server.handler(<Server>)"""
    def __init__(self, addr):
        self.addr = addr

    async def start_server(self, handler_method):
        self.server = await asyncio.start_server(handler_method, self.addr[0], self.addr[1])
        self.addr = self.server.sockets[0].getsockname()
        print(f"Serving on {self.addr}")
        async with self.server:
            await self.server.serve_forever()

client.py

from aserver import Client
import asyncio

client = Client()

async def client_run():
    try:
        await client.connect(("192.168.0.11", 56500))
        await client.send_bytes(b'Hi Echo Server!')
        await client.recv(1024)
    finally:
        # 确保无论是否出错,连接都会被关闭
        await client.close_conn()

asyncio.run(client_run())

server.py(优化细节)

import aserver as srv
import asyncio

# 将地址从列表改为元组,符合Socket API的标准格式
server = srv.Server(("192.168.0.11", 56500))

async def echo_server(reader, writer):
    data = await reader.read(1024)
    message = data.decode()
    addr = writer.get_extra_info('peername')
    print(f"Received {message} from {addr}")
    print(f"Echoing {message} back")
    writer.write(data)
    await writer.drain()
    print(f"Closing connection with {addr}")
    writer.close()
    await writer.wait_closed()  # 新增:等待连接彻底关闭

asyncio.run(server.start_server(echo_server))

关键优化点说明

  • 抛弃原生Socket直接使用asyncio流API:asyncio.open_connection和asyncio.start_server是官方推荐的异步网络编程方式,自动处理事件循环和异步IO,避免手动操作Socket的复杂度和错误。
  • 确保资源安全释放:客户端用finally块保证连接关闭,服务器端新增await writer.wait_closed()确保连接彻底释放,避免资源泄漏。
  • 修正地址类型:将服务器初始化的地址从列表改为元组,符合Socket API的标准参数格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:05:49