{"id":15538626,"url":"https://github.com/bashkirtsevich-llc/aioudp","last_synced_at":"2025-05-07T16:08:17.219Z","repository":{"id":57409207,"uuid":"190182521","full_name":"bashkirtsevich-llc/aioudp","owner":"bashkirtsevich-llc","description":"Asyncio UDP server","archived":false,"fork":false,"pushed_at":"2024-07-30T20:12:07.000Z","size":31,"stargazers_count":24,"open_issues_count":1,"forks_count":7,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-09T12:33:55.665Z","etag":null,"topics":["async","async-await","async-functions","async-programming","asynchronous","asynchronous-programming","asynchronous-tasks","asyncio","asyncstorage","asynctask","socket","socket-io","socket-server","throttling","throttling-mechanism","throttling-server","udp","udp-protocol","udp-server","udp-socket"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/aio-udp-server/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bashkirtsevich-llc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-04T10:47:38.000Z","updated_at":"2024-07-30T20:12:11.000Z","dependencies_parsed_at":"2024-10-31T10:03:27.324Z","dependency_job_id":"0911b16e-ddd0-4ee3-93fb-274e1815ac0a","html_url":"https://github.com/bashkirtsevich-llc/aioudp","commit_stats":{"total_commits":16,"total_committers":4,"mean_commits":4.0,"dds":0.5,"last_synced_commit":"0f026566e45f58df5d511916720badfd82d38c80"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bashkirtsevich-llc%2Faioudp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bashkirtsevich-llc%2Faioudp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bashkirtsevich-llc%2Faioudp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bashkirtsevich-llc%2Faioudp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bashkirtsevich-llc","download_url":"https://codeload.github.com/bashkirtsevich-llc/aioudp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":233352262,"owners_count":18663265,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","async-await","async-functions","async-programming","asynchronous","asynchronous-programming","asynchronous-tasks","asyncio","asyncstorage","asynctask","socket","socket-io","socket-server","throttling","throttling-mechanism","throttling-server","udp","udp-protocol","udp-server","udp-socket"],"created_at":"2024-10-02T12:05:13.523Z","updated_at":"2025-01-10T13:34:30.877Z","avatar_url":"https://github.com/bashkirtsevich-llc.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Asyncio UDP server\n[![Build Status](https://travis-ci.org/bashkirtsevich-llc/aioudp.svg?branch=master)](https://travis-ci.org/bashkirtsevich-llc/aioudp)\n\nYet another async UDP server. Based on bare sockets.\n\n**Killer-feature**: bandwidth throttling for uploading \u0026 downloading.\n\n\n## `UDPServer.__init__`\n\nUDP server constructor.\n\nArguments:\n* `upload_speed` — maximum outgoing traffic speed in \"byter per second\" (_default: `0` — unlimited_);\n* `download_speed` — maximum incoming traffic speed in \"byter per second\" (_default: `0` — unlimited_);\n* `recv_max_size` — maximum socket window size for receiving (_default: `262144`_).\n\n\n## `UDPServer.run`\n\nServer startup function.\n\nArguments:\n* `host` — socket bind host/interface (e.g. \"0.0.0.0\", \"127.0.0.1\" or \"localhost\");\n* `port` — socket listen port;\n* `loop` — event loop.\n\n\n## `UDPServer.send`\n\nEnqueue data for sending.\n\nArguments:\n* `data` — **bytes** or **bytearray** data for sending;\n* `addr` — tuple of host and port (e.g. `(\"127.0.0.1\", 9876)` or `(\"some.domain.com\", 5556)`).\n\n\n## `UDPServer.subscribe`\n\nSubscribe coro or future on a datagram received event.\n\nArguments:\n* `fut` — coroutine or future with arguments `data` and `addr`.\n\n\n## `UDPServer.unsubscribe`\n\nUnsubscribe coro or future from a datagram received event.\n\nArguments:\n* `fut` — coroutine or future.\n\n\n## Virtual events\n\n* `UDPServer._connection_made()` — virtual method, call after socket bind successfully;\n* `UDPServer._socket_error(data, addr)` — virtual method, call when got socket error;\n* `UDPServer._datagram_received(data, addr)` — virtual method, call each time when server got incoming data, can be used for modify data before pass it to subscribers;\n* `UDPServer._notify_subscribers(data, addr)` — virtual method, call with params returned from `_datagram_received`. \n\n\n## Example\n\n```python\nimport asyncio\nimport datetime\n\nfrom aioudp import UDPServer\n\n\nclass MyUDPServer:\n    def __init__(self, server, loop):\n        self.server = server\n        self.loop = loop\n        # Subscribe for incoming udp packet event\n        self.server.subscribe(self.on_datagram_received)\n        asyncio.ensure_future(self.do_send(), loop=self.loop)\n\n    async def on_datagram_received(self, data, addr):\n        # Override virtual method and process incoming data\n        print(datetime.datetime.now(), addr, data)\n\n    async def do_send(self):\n        while True:\n            # Any payload\n            payload = b'd1:ad2:id20:k\\xe7\\x90\\xcd\\x0c_R\\xfe\\x82\\xeb\\xa8 x\\x14\\xb4-\\x8e0\\xe5\\x086:target20:\\x11\\x8e\\xcc,\\x89\\xa4\\x99\\xf98E\\x98\\x7f!\\xa7w\\rz\\x1b\\x14de1:q9:find_node1:t2:#K1:y1:qe'\n            # Delay for prevent tasks concurency\n            await asyncio.sleep(0.001)\n            # Enqueue data for send\n            self.server.send(payload, (\"router.bittorrent.com\", 6881))\n\nasync def main(loop):\n    # Bandwidth speed is 100 bytes per second\n    udp = UDPServer(download_speed=100, upload_speed=100)\n    udp.run(\"0.0.0.0\", 12346, loop=loop)\n\n    server = MyUDPServer(server=udp, loop=loop)\n   \n\nif __name__ == '__main__':\n    loop = asyncio.get_event_loop()\n    loop.run_until_complete(main(loop))\n    loop.run_forever()\n```\n\nOutput:\n\n```\n2019-06-04 16:04:07.761576 ('67.215.246.10', 6881) b'd2:ip6:Z\\x97\\'X0:1:rd2:id20:2\\xf5NisQ\\xffJ\\xec)\\xcd\\xba\\xab\\xf2\\xfb\\xe3F|\\xc2g5:nodes416:\\x02\\xf7\\xb7\\x1d\\x94\\xb1\\x00\\xe8\\x84\\xca\\x9c\\xc3\\xb09\\xbb\\x04*P\\x8cQ\\x1f\\x7fF\\xa9\\x1a\\xe1\\x00\\x13\\x99W\\x14\\xb1\\x99\\x8b\\xff\\x8e\\xda2\\xb3 \\xac\\x82\\xef0sCl\\xda+G\\xc4\\x91\\x17bO,\\xe8\\xbc\\x9e\\xeb+\\xfc.\\xe6\\xf8\\xb0\\x82\\xee~\\x17 \\xebvF\\x83\\xf8\\x83\\xc1\\xdaK\\x1b\\x83\\x17\\xfb!\\xab\\x1e\\x97T\\xa3\\xfa\\x9a\\x14Q$\\x06)\\\\\\xad\u003eO\\x03\\xc4\\x91\\x9f/7\\xf6\u003e]|\\xe0\\xc6f\\x1eq\\xfd\\xcc\\x0e\\xbe\\xd0\\x85\\xde\\xf9\\xbeJc\\xe3e\\xe5\\x9e\\x9d\\xca})P\\xa5\\xfd\\x8c\\xb66\\xb9\\xba\\x0f\\xfc\\xb1\\xb9\\xa3 E\\xc9*\\x1f\\xd1I\\xb1r9\\xfaI\\xf1\\xf1\\xbb\\xe9\\xeb\\xb3\\xa6\\xdb\u003c\\x87\\x0c\u003e\\x99$^R\\xbc\\x85\\xd3\\xb3C\\xab}\\xbf6\\xcc\\x11\\x7fv\\xde\\r\\xed\\xa4q\\xdd\\x04#\\x8d\\xd8j7$[\\xe5e\\\\\\xf9V\\x166\\xb1P\\x7f\\xa01v\\xf49\\xb9\\x9a\\x12*\\xad\u003cQ@\\xa6\\x8d\\xd5\\xe6wN\\xa2\\x87\\xaf|\\xb4KslP\\xf5\\xd0h\\xaf\\x1c\\xb5\\xb6\\xc0\\xc9\\xfa\\x0c\\xfe\\xe8\\xb92\\n\\xb7\\xda\"8\\x019\\x95\\xe8\\xef\\xc1u\\xa4$\\xe5\\x0c!\\xe2\\x10j\\xff\\x10\\xeb\\xffu\\x02\\x87t\\x9f\\x01|\\xa4b\\x87\\xc4\\xa0.\\xd2g\\x9f\\xf6\\xd1\\xc2\\xfd\\xef\\xa1!a\\x04\\xdf\u003c\\x97)\\xbe\\xd1\\x81l\\xb1?W\\t\\xbb\\xc1\\xbd\\x04\\x8ec\\xf8\\x08\\xcd\\x1av\\x1a\\xa9\\xb3R^\\xb5{\\x11\\x1a\\xe1C\\xe1\\xb43\\x04\\x03Wl\\xd1E\\xa6\\x0f\\xf7\\xcbQ\\t\\x84W\\xd6\\xebD\\'\\xdd=\\xb1\\xc9\\xed\\xc6C\\xf9\\x7f\\xfbg\\xf9$\\x0e\\x0b~\\xa5\\xae\\xfdnvr\\xe7\\xc4.\\xf8(\\x90\\xa4\\x84C\\xe9\\xccK4r\\xc6=\\xf1\\xc09\\xdf{\\xfc\\x10\\xe9\\xd9\\xd8\\xa5\\xdd.\\x00\\x88\\x0e\\xe7]e1:t2:#K1:y1:re'\n2019-06-04 16:04:12.622861 ('67.215.246.10', 6881) b'd2:ip6:Z\\x97\\'X0:1:rd2:id20:2\\xf5NisQ\\xffJ\\xec)\\xcd\\xba\\xab\\xf2\\xfb\\xe3F|\\xc2g5:nodes416:\\x1e\\xe4\\xb8\\x96\\xf5E;\\x13\\r\\x89\\n\\x1c\\xdb\\xae2 \\x9aP\\xee\\xcb\\xa0\\xb0\\xcbq\\xa4X\\x80\\x8c\u003e\\x91:M\\xb67%kY\\xc7\\xb5\\xe1\\xe7\\x901_u\\\\\\xbd(g\\xeb[\\xa7-\\x1fl\\x1e\\xd6\\x93\\xe8g\\xdam\\n;\\xa8y \\xf4K\\x18\\xe0\\x11z\\xfe\\xa6\\xf6\\xc9\\xcfe\\xcb\\xf9\\x7f+\"92\\xfb/\\xd8C\u003eK\\x1a\\xf9\\xe8#\\x86\\x8dy\\x07\\xa1\\x94\u003e\\x81\\x17_\\xcd\\xe9\\x03?\\x96pX\\x1c\\xe8v{\\xa5W,_ \\x0f|Oi\\x8bg\\xc5J\\xfd#\\x9e\\xf7\\xdd\\xc4\\xa4\\xb9\\xd0\\x8f\\xbd\\x9d\\x98\\xfaD\\x91N}U{j\\xd7\\xfak\\')\\xcdr(\\xc3\\xdc\\xc6\\xd7\\x9b=\\x1d\\x12/\\xa4\\xd5A\\x8f[\\x98\\x07\\x10EHq#\\xcc\\xb8\\xae\\xf00\\xd4\\xfd(\\xe5fj\\xbb\\xdd\\xa5s\\x8b\\xec:\\xb1\\x1d\\x93%)S\\xdf.\\xb3\\x17\\x95\\x9b\\xc8\\xc0\\x95\"\\x86\\x81\\x16\\x8d]\\xdau\\x15S\\xbcN:\\x9d\\x83I+Vk\\xc4\\x91\\x0b9t\\xbdv`\\xb2\\x8d7\\xae\\t\\xb1\\x8c\\x96\\x9f\\x1c\\xa0B\\xd0\\x93\\xbfd\\x8e\\xe7\\xdf`\\x14\\x13\\'\u003c\\x92Pn:u\\xa0\\n\\xc3\\xcd\\x01\\x12H\\xc65\\xeb\\xa2X\\xc8\\xd6\\x0b\\x81\\x1b\\xcf\\x89\\xbco$\\x8a\\xf97\\x920u\\xb8i\\xde\\x15\\x19\\xc4\\x8f\\xfb\\xc0\\xb1\\xcf\\x99\\xd9e1\\xf6u\\x01\\xb7\\x1e\\xc4\\x80\\xca\\x0e\\xcawuv\\xc9\\xaf[\\x0b\\xd4\\x99\\xf4[\\xf1\\x8ck\\x1a\\xe1r\\xc3\\xb4(\\xb8ba\\x98\\x8b\\x1e\\xb4TN\"\\xa7F5B\\xcb\\x0f\\x05\\x9e\\xed-b\\x82\\xb8\\x8d\\xed\\xf7\\xaf?,\\xc5)z\\xd2f\\xc1\\xda`.\\xf0.!\\xf2H\\xbezs\\xf3\\x8c\\t\\x9c\\x9d\\xe8\\x87Q\\xf4\\xe9\\x8fJ\\x0c\\x16\\xa8\\xc55Q\\x878\u003c\\x04.0Bc!\\xade1:t2:#K1:y1:re'\n2019-06-04 16:04:17.483860 ('67.215.246.10', 6881) b'd2:ip6:Z\\x97\\'X0:1:rd2:id20:2\\xf5NisQ\\xffJ\\xec)\\xcd\\xba\\xab\\xf2\\xfb\\xe3F|\\xc2g5:nodes416:k*[\\x0c1\\x9a\\xb1\\xd6\\xe5\u003eG\\x0c\\xac\\xe3v0\\xd0\\xc2\\xb7\\x8cI\\x93\\xb7\\xcd\\xa8\\xf1\\xca(\\xf8\\xc0\\xe0\\xa6\\xd4\\xda*\\xd4\\xf1\\xedc\\xb4\\xdf\\xdf\\xe2Q\\x1a\\xe9^\\t\\x8f\\xfa\\x1a\\xe1$Wr\\xe18\\x1e\\x9a\\xce\\xabW}\\xbfLY\\x05\\xbd\\xce\\xa0\\x0e\\xb1_\\x19\\xdf\u003e\\xcaJS\\x00H\\xdf\\x8d\\xeedn\\xd7\\x07-\\x9f\\x8at\\xb0\\x14\\xbe\\x8d\\x1d\\x0eO\\xa7\\x97\\xa3\\x83\\xa9\\xb2\\xff\\xc9K\\x97\\x01m\\xbc\\xcb\\xc3\\x001vR\\'s\\xffyr\\x82UF\\\\z\\xafG\\x8f\\xc8U\\xcf}+\\x97\\x90\\xa2\\x1b\\x11\\xef\\xbfs\\x80Q\\xff\\x1dc\\x14%\\xe8\\x87\\xac!\\xadz\\xbd\\xcc\\xbfq\\xaex0\\x7f(}jY[W\\xdcsx\\n|F\\x86\\xed\\xa3\\x1a\\xe1,\\x03\\x87to\\xd2X\\x12\\x00\\x90\\t\\xcfu\\xec_m\\x15\\x02\\xe1\\xf6\\xd4\\x98\\x93\\xfa\\x1a\\xe1\\xc8\\xa1-tC!\\xd1X\\xb0\\xc9M\\xc8\\xf2\\x94|\\xca\\x80j\\xb8\\x04\\x05\\xceB\"_\\xc3H\\xf1i\\x86\\xb6\\x07Z=\\xc2\\xb1`m\\xab\\xbc\\xbeB\\xb8\\nVM]Q\\x1cp\\xc2L\\x83\\xca\\xe7\\xed\\x1e\\x10\\x9d\\xc9\\xde\\xdc[c\\xef\\xc2_]+N\\xaaJ\\xc9E0\\xf5\\x1b\\x16q\\xe1/\\x97w\u003ea\\x94\\x10\\x0f\\x94\\xc2\"\\xd6\\x89+\\xa7\\x01\\\\w%\\x90Z_\\x1a\\xe1\\xd9\\xf5\\xff\\xb5D\\xf2\\x8d\\xbc^[j\\x16\\xb9H\\xe3.+\\r\\x87\\xa5aU\\xafMT\\xec\\x80\\x02\\x9bP\\xf5\\xc7\\xe9\\x8e\\x9e\\x94\\x96\\xc8\\xcdu\\xa1\\xc1.\\xa7 \\xb5I\\x0b\\x9d\\xef\\xd0\\x8ff\\x91+\\xc2\\xe0\\xeb/\\xbe\\x05\\x87\\xac\\xd8\\xb8vA\\xe8?V\\xa3\\xfdJ\\xc1\\x9f\\xe8\\xc4\\x91=\\xc4\\x16H\\xbdP\\x1fv5x9\\x02\\'N]Zh\\xed\\xc9\\xc3\\xb5\\xae:\\x04\\xc8\\x04e1:t2:#K1:y1:re'\n2019-06-04 16:04:22.345648 ('67.215.246.10', 6881) b'd2:ip6:Z\\x97\\'X0:1:rd2:id20:2\\xf5NisQ\\xffJ\\xec)\\xcd\\xba\\xab\\xf2\\xfb\\xe3F|\\xc2g5:nodes416:+S\\xdc\\x8c\\xc8%~ \\x12\\xd3\\xd9@\\xa9X4\\x9at\\xcc\\x8a\\xf9z\\x08\\x1d\\x16h/\\xf2}\\xb7I\\xd9\\x8fP\\x81(\\x9d\\xed\\xae\\xa5\\xe5\\xe4S1,\\xf0-\\xaeavL\\xc4\\x91~\\xd5\\x01`o\\xa8\\xc4\\xe0\\xfa \\xa5\\xf0\\xf1~`\\x0c\\x19[+\\x85\\xbb\\xd0\\x0bp\\xf3\\x8c\\xe98S\\xcd`=n|\\xa8\\x8c\\xa4~\\xfc\\xedg\\xce\\xff\\x8f\\x13}g\\xfc\\xc9)\\xa8\\x89L\u0026]\\\\\\xb3M\\xc6NUE\\x7f\\xb8CQ\\x82\\xe1{C\\xba\\xaf\\x884g\\x9a\\xf3\\x8c\\x1a\\xe0\\xbb\\x1a\\x12\\xafCQ\\x1e\\x18\\x91;\\x80P\\xee\\xf0\\xdc\\t\\xc1m.\\xe4\\x04\\xda1\\xff\\x93?\\xa0r\\xc5\\x1d\\x9c\\x1f\\xc7\\xf2\\x0e[\\xc9\\tV4\\x94\\x02w\\xc2\\\\b\\x03+\\x1a\\xe1\\xc4\\x80#z0\\x14\\x9d}Kj\\xbe\\xf2\u003e\\xa5\\xf8k\\x12\\x9a|u\\xb0:\\xc1,U\\r\\xc7kE\\xa1UY\\x1e~:r\\x14\\xb6p\u0026\\xd7\\xdf\\xaf\u003e\\x9b\\xa5b\\xb5\\xcd\\x1f\\xc4\\x91Z\\xdf\\x1a\\x1f\\xdb\\x9a\\x84\\tu\\xff\\xda(\\xddqy}nT\\xaa\\x8f%\\x06.\\xc9\\xda\\xe4\\xc0\\x9a\\x03\\x9c\\x12?\\xf1s[\\xb1\\xd7;\\xe3)\\xb9[o\\r\\xb6=\\xb57\\x98\u0026\\xc4\\x91.\\xd1\\x87)5\\xf5s\\xb8\\xc9z\\xc4\\x9d\\x063Kw\\xaf\\xcc\\x046\\xdbN\\xcf,\\xf3\\x8c\\xaa\\x85\\xee\\xd0e\\xfa\\xca\\xd2\\x93\\x82\\xe2\\x98\\xeaA\\xdc\\xbd\\xaf\\x97F\\xe9r\\x19\\xb4i\\xde~\u003e\\x82\\xfb\\xe9y#vJ\\xe4\\x8e\\x0e\\xd1\\xee]\\xe0qk(\\xb2\\x92\\x95\\xff\\x02\\n\\x98\\x9c\"\\xcaY\\x8d\\xb6\\x81a\\xa1\\xf9\\xc1\\nX\\xb4\\x9e\\xcfo\\xbf\\xa3j\\x8fH1\\'7\\xc4\\x91v\\xd1_\\xec\\xe4\\xe1\\x1f\\xcb\\xd5\\xbd\\xf43\\x0c\\'\"\\x04\\xa5\\xa2\\x0f\\xd0\\x05\u003e+\\xb1 Xe1:t2:#K1:y1:re'\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbashkirtsevich-llc%2Faioudp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbashkirtsevich-llc%2Faioudp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbashkirtsevich-llc%2Faioudp/lists"}