简体   繁体   English

C++ UDP 从客户端接收到第一个数据包后,套接字无法从服务器发送回客户端

[英]C++ UDP Socket not working to send back from server to client after receiving first packets from client

Writing a UDP client-server app in C++ (done that lots of times before in many languages in the past 15 years), but somehow this one is not working correctly.在 C++ 中编写 UDP 客户端-服务器应用程序(在过去 15 年中以多种语言完成了很多次),但不知何故,这个应用程序无法正常工作。

I cannot post actual code nor minimal reproducible app at the moment but I am willing to pay for live help if anyone is available to help solve this quickly with screensharing.我目前无法发布实际代码或最小的可重现应用程序,但如果有人可以通过屏幕共享帮助快速解决此问题,我愿意支付实时帮助。

I think this is a particularity with C++ sockets and the way I am using them in this specific app which is quite complex.我认为这是 C++ sockets 的特殊性以及我在这个非常复杂的特定应用程序中使用它们的方式。

Basically the issue is that the packets sent from the server to the client are not received by the client, only when said client is on a separate nat.基本上问题是客户端没有收到从服务器发送到客户端的数据包,只有当所述客户端位于单独的 nat 上时。 When both in same local networking and using their local IP, everything works as expected.当在同一本地网络中并使用其本地 IP 时,一切都按预期工作。

Here is what I am doing:这是我正在做的事情:

  1. Client sendto(...) packets through UDP to the server using a specific server host and port 12345 (and keeps sending these non-stop)客户端sendto(...)数据包通过 UDP 使用特定的服务器主机和端口 12345 发送到服务器(并不停地发送这些)
  2. On another thread, client bind(...) on port 12345 and "0.0.0.0" and tries to poll() and recvfrom() in a loop (poll always returns 0 here when client is on a separate nat)在另一个线程上,客户端在端口 12345 和“0.0.0.0”上bind(...)并尝试在循环中poll()recvfrom() (当客户端在单独的 nat 上时,poll 总是在此处返回 0)
  3. Server bind() on port 12345 and "0.0.0.0" then poll() and recvfrom() in a loop服务器bind()在端口 12345 和 "0.0.0.0" 然后poll()recvfrom()循环
  4. Upon receiving the first UDP message from a client, it starts a thread for sending UDP messages back to the client on a new socket , using the sockaddr_in that it got from the recvfrom() to pass in the sendto() commands.在从客户端接收到第一条 UDP 消息后,它启动一个线程,用于在新套接字上将 UDP 消息发送回客户端,使用从recvfrom()获得的 sockaddr_in 传递sendto()命令。

Result: Server perfectly receives ALL messages from all clients, and sends all messages back to all clients, but any client that is not on the same NAT will never receive any messages ( poll() always returns 0).结果:服务器完美地接收到来自所有客户端的所有消息,并将所有消息发送回所有客户端,但任何不在同一个 NAT 上的客户端将永远不会收到任何消息( poll()始终返回 0)。

As far as I understand it, when the client sends a UDP message to the server on a specific remote port (12345 in this case), it will punch a hole in its NAT so that it can receive messages back from the remote server on that port...据我了解,当客户端在特定远程端口(在本例中为 12345)上向服务器发送 UDP 消息时,它将在其 NAT 上打一个洞,以便它可以从该远程服务器接收消息港口...

I tested five different client network configurations:我测试了五种不同的客户端网络配置:

  1. Local network with the server, using local IP addresses (WORKS)与服务器的本地网络,使用本地 IP 地址(WORKS)
  2. Local network with the server while client is using a VPN thus going through a remote NAT (DOES NOT WORK)客户端使用 VPN 时与服务器的本地网络,因此通过远程 NAT(不起作用)
  3. Local network with the server but client is using the WAN ip address to connect to the server (DOES NOT WORK)与服务器的本地网络,但客户端使用 WAN ip 地址连接到服务器(不起作用)
  4. Client at an actual remote network from a friend's connection, behind a router (DOES NOT WORK)来自朋友连接的实际远程网络中的客户端,在路由器后面(不起作用)
  5. Client going through a wifi hotspot created using my phone (DOES NOT WORK)客户端通过使用我的手机创建的 wifi 热点(不工作)

For all tests above, the server was correctly receiving all communications from clients.对于上述所有测试,服务器正确接收来自客户端的所有通信。

I also tried forcing the port to 12345 for the sendto() instead of using the sockaddr_in as set from recvfrom() , same issue.我还尝试将sendto()的端口强制为 12345,而不是使用从recvfrom()设置的 sockaddr_in ,同样的问题。

Am I doing anything wrong?我做错什么了吗?

If you want to help but need to see actual code, I can do that live with screen sharing and I will pay for the help.如果您想提供帮助但需要查看实际代码,我可以通过屏幕共享实时完成,我会为帮助付费。

Thanks.谢谢。

Also, if anyone can point me to a great site where I can pay for VERY QUICK help, please let me know, I don't even bother searching google because I really want actual advice from people who tried these services, not ads trying to rip me off...此外,如果有人可以将我指向一个很棒的网站,我可以在那里支付非常快速的帮助,请告诉我,我什至不费心搜索谷歌,因为我真的想要尝试这些服务的人的实际建议,而不是广告试图扯我...

Only the original receiver socket is allowed to reply to the client, because it's the client request that opens the port in the NAT.只允许原始接收方套接字回复客户端,因为在 NAT 中打开端口的是客户端请求。 So either use the same socket in the server to receive and reply, or get the port that the second server socket was bound to and transfer it with an initial message through the original server port, so that A can send to it and punch the hole.所以要么使用服务器中的同一个socket进行接收和回复,要么获取第二个服务器socket绑定的端口,并通过原始服务器端口传递一个初始消息,以便A可以发送给它并打孔.

It looks so strange to create two half duplex sockets when a socket is a full duplex communication object that I'd go with the first option.当套接字是全双工通信 object 时,创建两个半双工 sockets 看起来很奇怪,我使用第一个选项 go。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM