Search code examples
pythonudptwistedasyncore

Python asyncore UDP server


I am writing server application in Python that listens for requests, processes them, and sends a response.

All req/resp are send from the same address and port to the server application. I need to recv/send messages simultaneously, and the server need to recieve/send messages from/to the same port and address. I found some tutorials for asynchore sockets, but there are only examples for TCP connections.

Unfortunately, I need UDP. When I change SOCK_STREAM to SOCK_DGRAM in the create method, I get an error.

return getattr(self._sock,name)(*args)
socket.error: [Errno 95] Operation not supported

I tried to use twisted, but I dont know how to write the sender part, which can bind to the same port as its listening. The last result was blocked port.

Is there any way how to use asyncore sockets with UDP or how to use twisted to send from the same port? Some examples will be higly appreciated.


Solution

  • You can pretty much just write the sending and receiving part of your code and they'll work together. Note that you can send and receive on a single listening UDP socket - you don't need one for each (particularly if you want to send from and receive on the same address).

    from __future__ import print_function
    
    from sys import stdout
    
    from twisted.python.log import startLogging
    from twisted.internet import reactor
    from twisted.internet.protocol import DatagramProtocol
    
    class SomeUDP(DatagramProtocol):
        def datagramReceived(self, datagram, address):
            print(u"Got a datagram of {} bytes.".format(len(datagram)))
    
        def sendFoo(self, foo, ip, port):
            self.transport.write(
                (u"Foo datagram: {}".format(foo)).encode("utf-8"),
                (ip, port))
    
    class SomeSender(object):
        def __init__(self, proto):
            self.proto = proto
    
        def start(self):
            reactor.callLater(3, self._send)
    
        def _send(self):
            self.proto.sendFoo(u"Hello or whatever", b"127.0.0.1", 12345)
            self.start()
    
    startLogging(stdout)
    
    proto = SomeUDP()
    reactor.listenUDP(12345, proto)
    
    SomeSender(proto).start()
    
    reactor.run()