【问题标题】:Using UDP between remote server and client在远程服务器和客户端之间使用 UDP
【发布时间】:2018-01-06 23:16:57
【问题描述】:

我目前正在开发一个项目,该项目需要在服务器 Amazon Frankfurt)和多个主机(Arduino)之间进行 UDP 通信。我需要能够通过 UDP 将 JSON 数据从服务器发送到主机,并且它需要实时工作(时间在这里是一个真正的限制)。此外,主机会定期与服务器通话以通知服务器其状态。

我面临的问题是,虽然我可以 ping 服务器,但当我使用端口创建 UDP 套接字时,我收到此错误(对于任何端口):

errno99: 无法分配请求的地址

我也相信由于主机在不同的国家,我只能得到路由器的IP。主机将提供给用户,因此无法手动更改用户的路由器。我需要使用可以通过代码处理这些的东西。

我一直在搜索打孔和其他技术。我无法决定什么更适合我的情况。很抱歉我缺乏网络信息,感谢任何“阅读或搜索这些技术”的帮助或指导。

此代码在服务器上运行:

 import socket
 import time
 #Host's public IP
 UDP_IP_ADDRESS = "178.243.98.86"
 UDP_PORT_NO = 13000
 Destination = (UDP_IP_ADDRESS,UDP_PORT_NO)
 Message = "Hello, Server"
 senderSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 while True:
     senderSock.sendto(Message, Destination)
     time.sleep(1);

这段代码在我的机器上运行:

 import socket
 #Server's public IP
 UDP_IP_ADDRESS = "172.31.46.111"
 UDP_PORT_NO = 13000
 recieverSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 recieverSock.bind((UDP_IP_ADDRESS, UDP_PORT_NO))
 while True:
     data, addr = recieverSock.recvfrom(1024)
     print "Message: ", data

【问题讨论】:

  • 另外,您需要了解 UDP 是一种尽力而为、即发即弃的无连接协议,无法保证传送,您丢失一些数据包,所以你需要考虑到这一点。使用 UDP 的实时协议(如 VoIP)会考虑到数据包丢失的情况,并采取措施尽量减少对应用程序的影响。
  • 您能分享一下代码和整个堆栈跟踪吗?无法绑定到 IP 和端口与 NAT 问题无关。您肯定会遇到后者(除非您使用 IPv6 并且根本没有 NAT),但前者是另一回事。
  • @RonMaupin 这将是一个紧急警报系统,这就是我需要实时工作的原因。如果数据包丢失,我将多次发送相同的数据以恢复。
  • @Vovanrock2002 我尝试使用简单的服务器客户端示例,例如python wiki,并使用公共 IP。但是我没有尝试使用打孔,因为据我所知,在发送任何数据包之前,主机和服务器之间应该有一个实时连接。由于我的项目是一个紧急警告系统,我可能需要在任何未确定的时间发送警告
  • "如果数据包丢失,我将多次发送相同的数据以恢复。"我不确定 TCP 是否更合适。它将保证以正确的顺序传输数据。实时系统会理解丢失数据的发生,处理它没有所有数据的事实,然后继续前进。请求重新发送丢失的数据不是实时行为。

标签: sockets networking server udp real-time


【解决方案1】:

服务器

# Host's public IP
UDP_IP_ADDRESS = "178.243.98.86"

你不能依赖178.243.98.86。您的 arduino 位于一个或多个 NAT 后面。使用 NAT,当数据包离开网络时,您的数据包源和/或目标地址(以及最有可能的端口)会被重写。当此转换发生时,负责 NAT 的设备会记住此转换,但仅限于有限的时间段。该时间段通常默认为 24​​ 小时。

为了克服这个问题,由客户端发起与服务器的对话。在你的协议中引入一个新的消息类型,比如hey it's me, client #34。服务器应该将接收到的消息的源 IP 和端口与客户端 #34 关联一段时间,例如几小时。

在这种情况下,服务器将套接字绑定到地址和端口以及客户端。请注意,通过 UDP 发送的hey it's me, client #34 未加密,极易受到记录和重放攻击。我认为应该加密应急系统。

客户

# Server's public IP
UDP_IP_ADDRESS = "172.31.46.111"

172.31.46.111 不能是服务器的公共 IP,因为它是来自 an IPv4 private space 的地址。您可能想说“主机的私人地址”。绑定到这样的地址是有意义的。您收到错误很可能是因为您错误地确定了主机的 IP 地址。

有几种方法可以获取正确的 IP。如果您使用 DHCP(如果您从未想过要在 SOHO 中使用哪些 IP,则可以使用它),请登录您最近的路由器的管理界面并检查 DCHP 池。或者,Linux 和 Windows 具有执行相同操作的终端命令。对于 Arduino,您可能已经为其分配了一个静态地址。如果是,就绑定它。

【讨论】:

    【解决方案2】:

    您似乎还在服务器上打开了一个 tcp 套接字,并通过 udp 套接字从客户端连接到它。这是故意的吗?

    • gsn

    【讨论】:

    • 这应该在 cmets 部分,因为它不是答案。
    猜你喜欢
    • 1970-01-01
    • 2016-02-16
    • 2015-12-31
    • 1970-01-01
    • 2012-04-11
    • 2016-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多