Package: jetblack-datagram
jetblack-datagramA Python 3.8+ asyncio helper library for UDP datagram clients and servers.StatusThis is working, but still under continuous development, so there may be breaking changes.OverviewThis package provides a simple asyncio API for UDP datagrams, following a
similar pattern to the TCP streams API.A UDP server is started by callingstart_udp_serverwhich is
analogous to thestart_serverfunction provided byasyncio.
This returns aDatagramServer, which provides methods for reading (read), writing (sendto),
and closing (closeandwait_closed). This differs from the TCP variant which provides
a callback when a client connects with a read and write stream. This is because UDP is connection-less
so there is no connect (or disconnect) event. Also the data is sent and received inpackets,
so there seems to eb no benefit to provide separate read and write stream.The following creates a server, reads then writes some data.server=awaitstart_udp_server(('0.0.0.0',8000))data,addr=awaitserver.recvfrom()print(f"Received{data}from{addr}")server.sendto(b"Hello",addr)server.close()awaitserver.wait_closed()A UDP client is started by callingopen_udp_connectionwhich is analogous
to theopen_connectionfunction provided by theasynciolibrary for TCP, which returns aDatagramClient. This provides similar functionality to the
server, however theaddris not present when reading or writing, as the socket is bound
to the server address when it is created.client=awaitopen_udp_connection(('127.0.0.1',8000))client.send(b"Hello, World!")data=awaitclient.recv()print(f"Received{data}")client.close()awaitclient.wait_closed()InstallationInstall using pip.pipinstalljetblack-datagramGetting StartedTo create an echo server:importasynciofromjetblack_datagramimportstart_udp_serverasyncdefmain():server=awaitstart_udp_server(('127.0.0.1',9999))count=0whilecount<5:count+=1print("Reading")data,addr=awaitserver.recvfrom()print(f"Received{data!r}from{addr}")print(f"Send{data!r}to{addr}")server.sendto(data,addr)print("Closing")server.close()print("Waiting for server to close")awaitserver.wait_closed()print("Closed")print("Done")if__name__=='__main__':asyncio.run(main())To create an echo client:importasynciofromjetblack_datagramimportopen_udp_connectionasyncdefmain():client=awaitopen_udp_connection(('127.0.0.1',9999))print("Sending data")client.send(b"Hello, World!")print("reading data")data=awaitclient.recv()print(f"Received{data!r}")print("closing client")client.close()print("waiting for client to close")awaitclient.wait_closed()if__name__=='__main__':asyncio.run(main())UsageThe UDP protocol is connection-less, so unlike TCP it makes
no sense to provide a reader for each server connection, or to
provide a callback for connections.CommonThe following methods are common for both clients and servers.close() -> Noneasync wait_closed() -> NoneServerThe following methods are specific to the server.sendto(data: bytes, addr: Union[Address, str]) -> Noneasync recvfrom() -> Tuple[bytes, Address]ClientThe following methods are specific to the client.send(data: bytes) -> Noneasync recv() -> bytesHelpersThere is a helper to create the server and the client.For the server:asyncdefstart_udp_server(addr:Address,*,loop:Optional[AbstractEventLoop]=None,maxreadqueue:int=0)->DatagramServer:For the client:asyncdefopen_udp_connection(addr:Address,*,loop:Optional[AbstractEventLoop]=None,maxreadqueue:int=0)->DatagramClient: