Reputation: 18438
I have a computer that may be behind several firewalls, have only a private IP... pretty much not reachable from the outside world.
That computer periodically sends UDP data to a remote server (accessible from everywhere). That remote server will probably be in a different network than the UDP sender/client (or in a different country from that matter).
At a certain point, I have to send a package acknowledging that I received some data back to the "unreachable" computer, meaning: the client started a communication and I do have a socket.
I am afraid of the answer, because of what I read of the UDP protocol being mainly send-->disconnect-->forget about the package, but here goes the question. Is there any way of sending data using an existing UDP socket?
As a server, I'm using a very simple SocketServer class:
class MyUDPHandler(SocketServer.BaseRequestHandler):
def handle(self):
message_type = message_utils.extract_type(self.request[0])
message_cls = message_factory.get_class_by_message_type(message_type)
message = message_cls(
data=self.request[0],
came_from=self.client_address)
print "Got %s" % message
message.process()
self.request[1].send("test")
if __name__ == "__main__":
SERVER_HOST = settings.SERVER_HOST\
if hasattr(settings, "SERVER_HOST") else ""
SERVER_PORT = int(settings.SERVER_PORT)
server = SocketServer.UDPServer(
(SERVER_HOST, SERVER_PORT),
MyUDPHandler)
server.serve_forever()
The line self.request[1].send("test")
is failing with an error: [Errno 89] Destination address required
and the more I read about it, the more I think I won't be able to send data back to the client, at least not with this simple "send
" solution.
I can not change the client. Is there ANY way to send UDP data reusing a socket? Maybe there's a "savior" class out there I don't know about? Any hint will be appreciated.
Thank you in advance.
Upvotes: 1
Views: 4751
Reputation: 168836
You must use .sendto()
, not .send()
, like this:
self.request[1].sendto(
"test",
self.client_address)
Reference: http://docs.python.org/2/library/socketserver.html#socketserver-udpserver-example
The smallest responsive UDP socket server than I can create it this:
import SocketServer
class MyUDPHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.request[1].sendto( "test\n", self.client_address)
SocketServer.UDPServer( ("", 5432), MyUDPHandler).serve_forever()
It can tested from a Linux command line thusly:
$ nc -u 127.1 5432
Upvotes: 5
Reputation: 624
Although from the client and server perspective, UDP is connectionless, from the NAT/router's perspective, there is a connection that is maintained for two way communication. The server just needs to reply to the IP/port that it received the message from to reach the client.
The python doc has a good example of this: http://docs.python.org/2/library/socketserver.html#socketserver-udpserver-example
Basically it just needs the request address and use the sendto function
socket.sendto("test", self.client_address)
Upvotes: 1