【问题标题】:c++ Hole punching UDP(RTP)c++ 打孔UDP(RTP)
【发布时间】:2011-06-05 19:23:06
【问题描述】:

我正在做一个客户端-服务器语音聊天程序(非托管 C++,win32),其中客户端使用 TCP 连接到服务器,文本聊天/聊天室功能在 TCP 中完成,而所有音频传输都通过单独的 UDP/RTP 套接字发送(使用来自 JRTPLIB 的 API)。

所以从TCP连接知道IP,建立连接后就可以发送RTP套接字的端口号了。

问题在于,在 TCP 中,自从您建立连接以来,只有服务器需要进行端口转发才能双向进行通信,而在 UDP 中,您必须使用 recvfrom() - afaik 需要端口首先在客户端打开,这是我不想要的(如果您查看任何多人游戏或 VoIP 客户端,则不需要)

阅读有关 UDP Hole Punching 的资源(例如 http://en.wikipedia.org/wiki/UDP_hole_punching),例如,他们不断提到开始与服务器进行 udp 对话。就是这样——你如何在客户端不必打开任何端口的情况下与服务器实际开始 udp 对话(双向)?在 TCP 中,正如我提到的,您只需要 connect() 到服务器,就可以双向通信。

另外——我知道 RTP 是基于 UDP 构建的,但是关于 RTP 打孔(同样,使用 JRTPLIB)还有什么我应该知道的与 UDP 不同的吗?

提前致谢!

【问题讨论】:

  • 我有点困惑 - 为 NAT Traversal 完成了 UDP 打孔,即当您需要连接点对点并且两个点都位于专用网络(或路由器)时。服务器仅用作“配对”两个客户端的一种方式。这就是你想要做的吗?
  • 我正在尝试在连接到服务器的客户端之间实现 UDP/RTP 连接,而无需客户端打开任何端口。据我了解,客户端与服务器交换 IP/端口,然后服务器在客户端之间共享它,以便它们可以直接相互通信
  • “开放任何端口”是什么意思?必须打开端口才能进行通信,这就是 udp 打孔的作用。
  • 那么网络游戏和ventrilo/skype是如何实现通信的呢?在这些应用程序中,您不需要为 UDP 通信打开任何端口
  • @KaiserJohaan 客户端必须发送第一个 UDP 数据包。这会“打开”客户端网关中的端口,因此它可以从服务器接收数据。

标签: c++ network-programming udp rtp hole-punching


【解决方案1】:

“打开端口”有两种可能的定义。一种是用 bind() 为 UDP 或 listen() 为 TCP 打开一个端口,另一种是在防火墙中打开一个端口。

您需要使用 API 调用打开一个端口才能接收某些内容,没有办法绕过它,但您可能意识到这一点,所以我认为您的意思是在防火墙中打开一个端口。但是您不需要在发起通信的一方(客户端)执行此操作。这适用于 TCP 和 UDP,除非您的防火墙设置为非常偏执的模式。任何合理的防火墙都将允许服务器对 UDP 端口的响应,前提是在某个时间之前从该端口向同一服务器发送了数据报。如果双方都在 NATing 防火墙/路由器后面,您只需要打孔。这就是 Skype 的做法。

此外,您甚至不必为 recvfrom() 之类的东西操心。您可以只 bind() 一个 UDP 套接字,然后使用 connect() 和 recv()/send() 或 read()/write(),就像使用 TCP 一样。

【讨论】:

  • 我明白了,这是有道理的。对于客户端,connect() 是否设置了此连接,或者您实际上是否必须 send() 某些东西以便防火墙随后接受该端口上的传入数据包?
  • @Kaiser,不,因为 UDP 是无连接协议,所有 connect() 调用只是设置默认地址来发送或接收,因此您不必每次都指定它。所以你必须先 send() 一些东西。
  • 我明白了。谢谢,我要试试这个!
猜你喜欢
  • 2012-11-30
  • 2011-06-14
  • 2014-10-17
  • 2019-04-11
  • 2019-01-13
  • 2013-01-29
  • 2012-02-26
  • 2011-10-11
  • 2012-02-12
相关资源
最近更新 更多