【发布时间】:2020-10-01 19:49:01
【问题描述】:
用 C++ 编写一个 UDP 客户端-服务器应用程序(在过去 15 年中用多种语言编写了很多次),但不知何故,这个应用程序无法正常工作。
目前我无法发布实际代码或最小的可重现应用程序,但如果有人可以通过屏幕共享帮助快速解决此问题,我愿意为实时帮助付费。
我认为这是 C++ 套接字的特殊性,以及我在这个非常复杂的特定应用程序中使用它们的方式。
基本上问题是客户端不会收到从服务器发送到客户端的数据包,只有当所述客户端位于单独的 nat 上时。 当在同一个本地网络中并使用他们的本地 IP 时,一切都按预期工作。
这是我正在做的事情:
- 客户端
sendto(...)使用特定服务器主机和端口 12345 通过 UDP 向服务器发送数据包(并不断发送这些信息) - 在另一个线程上,客户端
bind(...)在端口 12345 和“0.0.0.0”上,并尝试循环访问poll()和recvfrom()(当客户端在单独的 nat 上时,这里的轮询始终返回 0) - 服务器
bind()在端口 12345 和“0.0.0.0”然后poll()和recvfrom()在一个循环中 - 从客户端接收到第一条 UDP 消息后,它会启动一个线程用于发送
UDP 消息在新的套接字上返回给客户端,使用
sockaddr_in,它从
recvfrom()得到传递sendto()命令。
结果:服务器完美接收来自所有客户端的所有消息,并将所有消息发送回所有客户端,但任何不在同一个 NAT 上的客户端将永远不会收到任何消息(poll() 始终返回 0)。
据我了解,当客户端在特定远程端口(本例中为 12345)上向服务器发送 UDP 消息时,它会在其 NAT 上打一个洞,以便它可以从远程接收消息该端口上的服务器...
我测试了五种不同的客户端网络配置:
- 与服务器的本地网络,使用本地 IP 地址 (WORKS)
- 当客户端使用 VPN 时与服务器的本地网络因此通过远程 NAT(不起作用)
- 与服务器的本地网络,但客户端使用 WAN ip 地址连接到服务器(不起作用)
- 客户端在实际远程网络上,来自朋友的连接,在路由器后面(不起作用)
- 客户端通过使用我的手机创建的 wifi 热点(不起作用)
对于上述所有测试,服务器正确接收来自客户端的所有通信。
我还尝试将sendto() 的端口强制为12345,而不是使用recvfrom() 中设置的sockaddr_in,同样的问题。
我做错了吗?
如果您想提供帮助但需要查看实际代码,我可以通过屏幕共享实时完成,我会为帮助付费。
谢谢。
另外,如果有人可以将我指向一个很棒的网站,我可以在那里支付非常快速的帮助,请告诉我,我什至不费心搜索谷歌,因为我真的想要尝试这些服务的人的实际建议,而不是广告试图敲诈我......
【问题讨论】:
标签: c++ linux sockets udp hole-punching