{"id":9496,"library":"asyncio-dgram","title":"asyncio-dgram","description":"asyncio-dgram provides a higher-level, more convenient API for working with UDP datagram sockets in Python's asyncio framework. It simplifies common UDP operations like binding, connecting, sending, and receiving data with an async/await interface. The current version is 3.0.0, and it generally follows a release cadence driven by feature additions, bug fixes, and API improvements.","status":"active","version":"3.0.0","language":"en","source_language":"en","source_url":"https://github.com/jsbronder/asyncio-dgram.git","tags":["asyncio","udp","datagram","networking","sockets"],"install":[{"cmd":"pip install asyncio-dgram","lang":"bash","label":"Install stable release"}],"dependencies":[],"imports":[{"symbol":"bind","correct":"from asyncio_dgram import bind"},{"symbol":"connect","correct":"from asyncio_dgram import connect"}],"quickstart":{"code":"import asyncio\nfrom asyncio_dgram import bind, connect\n\nasync def udp_server(host, port):\n    async with bind((host, port)) as stream:\n        print(f\"Server: Listening on {host}:{port}\")\n        data, remote_addr = await stream.recv()\n        message = data.decode()\n        print(f\"Server: Received '{message}' from {remote_addr}\")\n        response = f\"Hello from server! You sent: '{message}'\".encode()\n        await stream.send(response, remote_addr)\n        print(f\"Server: Sent '{response.decode()}' back to {remote_addr}\")\n    print(\"Server: Stream closed.\")\n\nasync def udp_client(host, port, message):\n    async with connect((host, port)) as stream:\n        print(f\"Client: Sending '{message}' to {host}:{port}\")\n        await stream.send(message.encode())\n        data, remote_addr = await stream.recv()\n        response = data.decode()\n        print(f\"Client: Received '{response}' from {remote_addr}\")\n    print(\"Client: Stream closed.\")\n\nasync def main():\n    host = '127.0.0.1'\n    port = 9999\n\n    server_task = asyncio.create_task(udp_server(host, port))\n    # Give the server a moment to start listening\n    await asyncio.sleep(0.1)\n    client_task = asyncio.create_task(udp_client(host, port, \"Hello UDP World!\"))\n\n    await asyncio.gather(server_task, client_task)\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n","lang":"python","description":"This example demonstrates a simple UDP server and client using `asyncio-dgram`. The server binds to a port, receives a message, and echoes it back. The client connects to the server, sends a message, and receives the echo. Both use the `async with` syntax for managing the datagram stream."},"warnings":[{"fix":"Change `stream = await asyncio_dgram.bind(...)` to `async with asyncio_dgram.bind(...) as stream:` (and similarly for `connect`).","message":"As of version 3.0.0, the `bind()` and `connect()` functions no longer return the datagram stream directly. Instead, they return an asynchronous context manager that must be used with `async with`.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Always be mindful of UDP's connectionless nature. Verify remote addresses in `recv()` results if strict sender validation is needed, especially when using `bind()`.","message":"UDP is a connectionless protocol. While `asyncio_dgram.connect()` 'connects' the local socket to a specific remote address, it primarily filters outgoing and incoming packets on the local socket. It does not establish a persistent connection in the TCP sense, and `recv()` can still theoretically receive from other addresses if not explicitly handled or if the 'connected' state is not enforced by the OS.","severity":"gotcha","affected_versions":"All"},{"fix":"Implement application-level acknowledgements, retransmissions, or sequence numbering if reliability is required, or consider using TCP-based solutions (like `asyncio.start_server` / `asyncio.open_connection`) if strict reliability is paramount.","message":"UDP offers no reliability guarantees; packets may be lost, duplicated, or arrive out of order. `asyncio-dgram` does not implement any form of reliability on top of UDP. Applications must handle these possibilities or use a higher-level protocol.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Use `async with bind(...) as stream:` or `async with connect(...) as stream:` instead of `stream = await bind(...)`.","cause":"Attempting to `await` the result of `bind()` or `connect()` directly instead of using `async with` (a breaking change in v3.0.0).","error":"TypeError: 'coroutine' object is not an async context manager"},{"fix":"Ensure no other application is listening on the port. If running immediately after stopping a previous instance, wait a moment or choose a different port. On Linux, `sudo netstat -apun | grep <port>` can help identify the rogue process.","cause":"Another process is already using the specified UDP port, or the previous socket was not properly closed and the OS hasn't released it yet (common after a crash).","error":"OSError: [Errno 98] Address already in use"},{"fix":"Verify the remote host and port are correct and reachable. Check firewall settings on both sender and receiver. Ensure the remote server is actively listening for UDP packets.","cause":"When using `connect()` and sending, the remote server might not be running, or a firewall is blocking packets, preventing any response from being received within a reasonable timeframe (though `asyncio-dgram`'s `send` itself doesn't typically timeout for UDP, `recv` can).","error":"TimeoutError: [Errno 110] Connection timed out (when sending/receiving to a remote address)"}]}