Issue
When I execute the following script I get
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())
The example is from here. The only changes I made:
- Using an already created IPv6 socket by using the sock argument of create_datagram_endpoint.
- I have to do it this way, because I have to specify some options on the socket which I omitted in the example.
- Providing an address ("::1", 60000) in the transport.sendto function.
Can anyone explain what I am doing wrong and how to fix this?
I use Python 3.11.2 on Windows 10 21H2.
I have tried IPv4 (changing AF_INET6 to AF_INET and ::1 to 127.0.0.1 as well). Then the example works just fine. Using socket without the async framework also works, even for IPv6:
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
sock.sendto(b"11", ("::1", 60000))
Solution
The solution is to provide the flow info and scope id in the sendto
function:
self.transport.sendto(self.message.encode(), ("::1", 60000, 0, 0))
In addition there might be a second problem:
When the sendto
function is not called in the connection_made
callback, then the asyncio framework calls ov.WSARecvFrom
next which results in the same error ([WinError 10022] An invalid argument was supplied) because the socket is in the wrong state (receiving but no address is provided). The solution is to bind the socket before calling create_datagram_endpoint
: sock.bind(("", 0))
Some related bugs for further reading:
- https://github.com/python/cpython/issues/71687
- https://github.com/python/cpython/issues/72009
- https://github.com/python/cpython/issues/79726
Answered By - user18342360
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.