Skip to content Skip to sidebar Skip to footer

Easiest Way To Perform Asynchronous Socket Reading From Udp In Python?

I am trying to find the easiest way to read from multiple (around 100) udp datagram sockets in python. I have looked at tornado, but tornado touts http/tcp rather than udp support.

Solution 1:

The SocketServer module has a built-in UDP server with options for threading and forking.

Another option is the use the select module which will allow you to focus only on the sockets where data is already available for reading.

Solution 2:

I must confess I never used it, but maybe Twisted will suit your needs.

It supports lots of protocols, even serial connections.

Solution 3:

I'd like to add some comments on the initial question even though it already has an accepted answer.

If you have multiple connections which need independent processing (or at least processing with not much synchronization), its okay to use one thread per connection and do blocking reads. Modern schedulers won't kill you for that one. It is a fairly efficient way of handling the connections. If you are concerned about memory footprint, you could reduce the stack size of the threads accordingly (does not apply to python).

The threads/processes will stay in a non-busy waiting state for most of the time (while waiting for new data) and not consume any CPU time.

If you do not want or can not use threads, the select call is definetly the way to go. This is also low-level and efficient waiting and as a bonus, gives you the list of sockets which triggered.

Solution 4:

asyncoro supports asynchronous TCP and UDP sockets (among many other features). Unlike with other frameworks, programming with asyncoro is very similar to that of threads. A simple UDP client/server program to illustrate:

import socket, asyncoro

defserver_proc(n, sock, coro=None):
    for i in xrange(n):
        msg, addr = yield sock.recvfrom(1024)
        print('Received "%s" from %s:%s' % (msg, addr[0], addr[1]))
    sock.close()

defclient_proc(host, port, coro=None):
    sock = asyncoro.AsynCoroSocket(socket.socket(socket.AF_INET, socket.SOCK_DGRAM))
    msg = 'client socket: %s' % (sock.fileno())
    yield sock.sendto(msg, (host, port))
    sock.close()

if __name__ == '__main__':
    sock = asyncoro.AsynCoroSocket(socket.socket(socket.AF_INET, socket.SOCK_DGRAM))
    sock.bind(('127.0.0.1', 0))
    host, port = sock.getsockname()

    n = 100
    server_coro = asyncoro.Coro(server_proc, n, sock)
    for i inrange(n):
        asyncoro.Coro(client_proc, host, port)

asyncoro uses efficient polling mechanisms where possible. Only with Windows and UDP sockets it uses inefficient 'select' (but uses efficient Windows I/O Completion Ports for TCP if pywin32 is installed).

Solution 5:

I think if you do insist on using tornado's ioloop and want to do UDP socket processing, you should use a UDP version of the tornado IOStream. I have done this with success in my own projects. It is a little bit of a misnomer to call it UDPStream (since it is not quite a stream), but the basic use should be very easy for you to integrate into your application.

See the code at: http://kyle.graehl.org/coding/2012/12/07/tornado-udpstream.html

Post a Comment for "Easiest Way To Perform Asynchronous Socket Reading From Udp In Python?"