Asyncio UDP server with traffic throttling
Project description
Asyncio UDP server
Yet another async UDP server. Based on bare sockets.
Killer-feature: bandwidth throttling for uploading & downloading.
UDPServer.__init__
UDP server constructor.
Arguments:
upload_speed— maximum outgoing traffic speed in "byter per second" (default:0— unlimited);download_speed— maximum incoming traffic speed in "byter per second" (default:0— unlimited);recv_max_size— maximum socket window size for receiving (default:262144).
UDPServer.run
Server startup function.
Arguments:
host— socket bind host/interface (e.g. "0.0.0.0", "127.0.0.1" or "localhost");port— socket listen port;loop— event loop.
UDPServer.send
Enqueue data for sending.
Arguments:
data— bytes or bytearray data for sending;addr— tuple of host and port (e.g.("127.0.0.1", 9876)or("some.domain.com", 5556)).
UDPServer.subscribe
Subscribe coro or future on a datagram received event.
Arguments:
fut— coroutine or future with argumentsdataandaddr.
UDPServer.unsubscribe
Unsubscribe coro or future from a datagram received event.
Arguments:
fut— coroutine or future.
Virtual events
UDPServer._connection_made()— virtual method, call after socket bind successfully;UDPServer._socket_error(data, addr)— virtual method, call when got socket error;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;UDPServer._notify_subscribers(data, addr)— virtual method, call with params returned from_datagram_received.
Example
import asyncio
import datetime
from aioudp import UDPServer
class MyUDPServer:
def __init__(self, server, loop):
self.server = server
self.loop = loop
# Subscribe for incoming udp packet event
self.server.subscribe(self.on_datagram_received)
asyncio.ensure_future(self.do_send(), loop=self.loop)
async def on_datagram_received(self, data, addr):
# Override virtual method and process incoming data
print(datetime.datetime.now(), addr, data)
async def do_send(self):
while True:
# Any payload
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'
# Delay for prevent tasks concurency
await asyncio.sleep(0.001)
# Enqueue data for send
self.server.send(payload, ("router.bittorrent.com", 6881))
async def main(loop):
# Bandwidth speed is 100 bytes per second
udp = UDPServer(download_speed=100, upload_speed=100)
udp.run("0.0.0.0", 12346, loop=loop)
server = MyUDPServer(server=udp, loop=loop)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
loop.run_forever()
Output:
2019-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>O\x03\xc4\x91\x9f/7\xf6>]|\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<\x87\x0c>\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<Q@\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<\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'
2019-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>\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>K\x1a\xf9\xe8#\x86\x8dy\x07\xa1\x94>\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\'<\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<\x04.0Bc!\xade1:t2:#K1:y1:re'
2019-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>G\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>\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>a\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'
2019-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&]\\\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>\xa5\xf8k\x12\x9a|u\xb0:\xc1,U\r\xc7kE\xa1UY\x1e~:r\x14\xb6p&\xd7\xdf\xaf>\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&\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~>\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>+\xb1 Xe1:t2:#K1:y1:re'
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aio-udp-server-0.0.7.tar.gz.
File metadata
- Download URL: aio-udp-server-0.0.7.tar.gz
- Upload date:
- Size: 18.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/4.6.1 pkginfo/1.7.1 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.2 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e69bf1bca4bf40a46fc19d2a856106faf20309a83424d6fb162ac47cb2c4f674
|
|
| MD5 |
f35e17da2f64c31606dd433eea66c588
|
|
| BLAKE2b-256 |
43fdaab21755dbd0f7f15435beda77ff388a68e27ec9e87b88e5467f57a7094b
|
File details
Details for the file aio_udp_server-0.0.7-py3-none-any.whl.
File metadata
- Download URL: aio_udp_server-0.0.7-py3-none-any.whl
- Upload date:
- Size: 19.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/4.6.1 pkginfo/1.7.1 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.2 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b4aadd76814347b4801e47798bdaae2c2d680cc21ae40cd6d86c33ed2999055a
|
|
| MD5 |
2864826559462911e8666e994f8deb25
|
|
| BLAKE2b-256 |
f3c1e7aa5cab2fcb3d532270c3b4e1b0aceea3fdda1bb5971cd34e623f75f3ea
|