当我执行下面的脚本时,我得到
Send: Hello World!
Error received: [WinError 10022] An invalid argument was supplied
Error received: [WinError 10022] An invalid argument was supplied
Connection closed
import asyncio
import socket
class EchoClientProtocol:
def __init__(self, message, on_con_lost):
self.message = message
self.on_con_lost = on_con_lost
self.transport = None
def connection_made(self, transport):
self.transport = transport
print('Send:', self.message)
self.transport.sendto(self.message.encode(), ("::1", 60000))
def datagram_received(self, data, addr):
print("Received:", data.decode())
print("Close the socket")
self.transport.close()
def error_received(self, exc):
print('Error received:', exc)
def connection_lost(self, exc):
print("Connection closed")
self.on_con_lost.set_result(True)
async def main():
# Get a reference to the event loop as we plan to use
# low-level APIs.
loop = asyncio.get_running_loop()
on_con_lost = loop.create_future()
message = "Hello World!"
sock = socket.socket(family=socket.AF_INET6, type=socket.SOCK_DGRAM)
transport, protocol = await loop.create_datagram_endpoint(
lambda: EchoClientProtocol(message, on_con_lost),
sock = sock)
try:
await on_con_lost
finally:
transport.close()
asyncio.run(main())
这个例子是从这里开始的。我所做的唯一修改是:
- 通过使用create_datagram_endpoint的sock参数使用已创建的IPv6套接字。
- 我必须这样做,因为我必须在套接字上指定一些我在示例中省略的选项。
- 在transport.sendto函数中提供地址(“::1”,60000)。
谁能解释一下我做错了什么,以及如何解决这个问题?
我在Windows 10 21H2上使用Python 3.11.2。
我已经尝试过IPv4(将AF_INET6改为AF_INET,将::1改为127.0.0.1)。然后这个例子就可以正常工作了。使用没有异步框架的套接字也可以工作,即使是IPv6:
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
sock.sendto(b"11", ("::1", 60000))
1条答案
按热度按时间gcxthw6b1#
解决方案是在
sendto
函数中提供流信息和作用域ID:此外,可能还有第二个问题:
当
connection_made
回调函数中没有调用sendto
函数时,asyncio框架接下来会调用ov.WSARecvFrom
,这会导致相同的错误([WinError 10022] An invalid argument was supplied),因为套接字处于错误的状态(接收但没有提供地址)。解决方案是在调用create_datagram_endpoint
之前绑定套接字:sock.bind(("", 0))
一些相关的bug供进一步阅读: