UDP Hole Punching (c++/winsock)

UDP Hole Punching (c++/winsock)

本文关键字:winsock c++ Hole Punching UDP      更新时间:2023-10-16

stackoverflow用户!

我有一个必须处理p2p的应用程序,这就是我如何进行UDP打孔的方法。但我在执行方面遇到了麻烦。希望你能给我一些建议。

我有一台服务器,它工作得很好,可以将客户端相互介绍,但客户端无法连接,可能是因为我的小exp使用套接字。因此,客户端算法是:

  1. 创建udp套接字(套接字(AF_INET、SOCK_DGRAM、IPPROTO_udp))
  2. 通过sendto功能向服务器发送消息
  3. 使用recvfromlocker函数从服务器获取答案

在这三个步骤之后,我得到了对等端点。接下来,我尝试用两种方式连接客户端:

Way1

  1. 使用相同的套接字通过sendto函数向对等方发送数据,但传递另一个sockaddr
  2. 使用recvfromlocker函数收听(此时我收到WSAECONNRESET错误)

Way2

  1. 创建新套接字
  2. 绑定它
  3. 使用它向对等方发送数据
  4. 听着

这样,一个客户端绑定失败,另一个客户端侦听失败,并出现错误WSAEADDRINUSEWSAECONNRESET。我显然做错了什么,我们将非常感谢您的帮助。提前谢谢。

p.S.想分享一篇关于UDP打孔的好文章,以帮助那些对这项技术陌生的人:http://www.brynosaurus.com/pub/net/p2pnat/

如果您阅读recvfrom()的文档,它会显示:

WSAECONNRESET

远程侧执行硬关闭或中止关闭时重置了虚拟电路。应用程序应关闭套接字;它不再可用在UDP数据报套接字上,此错误表示先前的发送操作导致ICMP端口无法访问消息

这意味着您对sendto()的调用失败。如果一个或两个客户端都在路由器后面,这是有道理的。根据您的描述(以及缺乏代码),您实际上并没有执行任何穿孔来打开路由器,以允许客户端到客户端的数据包通过。您只向服务器发送了一条消息,允许客户端到服务器和服务器到客户端的数据包通过。每个客户端和服务器之间还需要进行几次数据包交换,才能在每一端进行打孔,正如您链接的文章中详细描述的那样。您真的在做文章中说的吗?