UDP Socketserver - 通过相同的套接字发送数据(不可能?)

时间:2013-04-18 15:50:42

标签: python sockets udp request

我的计算机可能位于多个防火墙后面,只有一个私有IP ...几乎无法从外部访问。

该计算机定期将UDP数据发送到远程服务器(可从任何地方访问)。该远程服务器可能位于与UDP发送方/客户端不同的网络中(或者在与该问题不同的国家/地区)。

在某个时刻,我必须发送一个包,确认我收到了一些数据回到“无法访问”的计算机,这意味着:客户端开始通信,我确实有一个套接字。

我害怕答案,因为我读到的UDP协议主要是发送 - >断开 - >忘记包,但这里提出了问题。有没有办法使用现有的UDP套接字发送数据?

作为服务器,我使用的是一个非常简单的SocketServer类:

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()

self.request[1].send("test")失败并显示错误:[Errno 89] Destination address required,我读的越多,我就越不能将数据发送回客户端,至少不会使用这个简单的“send”解决方案。

我无法更改客户端。是否有任何方法可以重用套接字来发送UDP数据?也许那里有一个我不知道的“救世主”课程?任何暗示都将受到赞赏。

提前谢谢你。

2 个答案:

答案 0 :(得分:5)

您必须使用.sendto(),而不是.send(),如下所示:

self.request[1].sendto(
  "test",
  self.client_address) 

参考:http://docs.python.org/2/library/socketserver.html#socketserver-udpserver-example

<小时/>

附加功能:

最小的响应式UDP套接字服务器比我可以创建它:

import SocketServer
class MyUDPHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        self.request[1].sendto( "test\n", self.client_address)
SocketServer.UDPServer( ("", 5432), MyUDPHandler).serve_forever()

它可以从Linux命令行进行测试:

$ nc -u 127.1 5432

答案 1 :(得分:1)

虽然从客户端和服务器的角度来看,UDP是无连接的,但从NAT /路由器的角度来看,有一个为双向通信而维护的连接。服务器只需要回复它收到消息的IP /端口即可到达客户端。

python doc就是一个很好的例子:http://docs.python.org/2/library/socketserver.html#socketserver-udpserver-example

基本上它只需要请求地址并使用sendto函数

socket.sendto("test", self.client_address)