Issue
I have a socket object created with socket(AF_INET, SOCK_DGRAM)
which I will be using it in an asyncio loop. However I couldn't find sendto
function in https://docs.python.org/3/library/asyncio-eventloop.html#low-level-socket-operations.
Can I safely assume that this function is a non-blocking system call which can be invoked inside an asyncio loop? Or should I submit it to run in another thread with run_in_executor
?
** Documentation states that it performs a system call which concerned me that it might block the entire loop.
Solution
No, you cannot expect socket.sendto
to be non-blocking.
Instead, use DatagramTransport.sendto:
Send the data bytes to the remote peer given by addr (a transport-> dependent target address). If addr is None, the data is sent to the target address given on transport creation.
This method does not block; it buffers the data and arranges for it to be sent out asynchronously.
The datagram transport is returned by the loop.create_datagram_endpoint coroutine:
transport, protocol = await loop.create_datagram_endpoint(factory, sock=sock)
EDIT - About your comment:
Is socket.sendto() equivalent to transport.sendto()?
No it's not, transport.sendto
uses loop.add_writer
to make the operation non-blocking. See the implementation.
I do not want to use this method because of it's implementation which enforce me to receive data through protocol with callback style.
The lower level of asyncio is based on callbacks and asyncio doesn't provide coroutine-based objects for UDP. However, I wrote a module that provides high-level UDP endpoints for asyncio.
Usage:
async def main():
local = await open_local_endpoint()
remote = await open_remote_endpoint(*local.address)
remote.write(b'Hey Hey, My My')
data, addr = await local.read()
message = "Got {data!r} from {addr[0]} port {addr[1]}"
print(message.format(data=data.decode(), addr=addr))
Output:
Got 'Hey Hey, My My' from 127.0.0.1 port 45551
Answered By - Vincent
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.