在实现C# Tcp打洞时遇到错误 - 无法在NAT后面连接

3
我有一个带有公共IP地址的服务器和一个运行在C#语言中的NAT后面的客户端机器。我尝试编写TCP打洞程序,但是在从服务器到客户端建立套接字时出现了错误。我的步骤如下:
1)首先,我与公共服务器建立套接字连接,并向其发送消息,并开始在端口17000上监听。
2)第二步,服务器收到消息并解析它。
3)第三步,在服务器端获取远程终结点IPAddress和端口号(=Nat路由器IPAddress和Port)。
4)第四步,尝试连接到套接字(NAT Ip,Nat Port),并从服务器向端口17000的客户端发送消息=>表示我已经将套接字连接到NAT路由器,并希望路由器将我的消息发送到NAT后面的客户端。
但是我遇到了以下错误: “由于所连接的方在一段时间后没有正确答复或连接的主机未能响应 X.X.X.X:24352,连接尝试失败。”
请问有人可以帮我解决这个问题吗?
提前致谢。

你的服务器是否在NAT后面? - usr
不,我的服务器拥有有效的公共IP地址。我可以从我的位于NAT后面的计算机连接到服务器并发送消息,但无法从服务器连接到我的计算机以发送消息。 - M.Zebeleh
你在第一步中是否使用了与你现在在第四步中列出的相同端口进行连接? - usr
1
好的,请发布一个最小的代码片段来演示问题。 - usr
顺便问一下,为什么你的服务器需要连接客户端?客户端不能直接连接服务器吗? - usr
显示剩余2条评论
1个回答

0

你的问题可能出在这里:

希望路由器将我的消息发送到NAT后面的客户端

NAT穿透(如打洞)取决于特定NAT的实现。您假设,由于NAT看到了来自客户端端口17000的数据包,并将其映射到某个NAT端口X,则它将转发所有从端口X返回的数据包到客户端。并非所有的NAT都是这样的!

来自Microsoft Technet:的信息。

定义了以下类型的NAT:锥形NAT:一种NAT,其中NAT转换表项存储内部地址和端口号与外部地址和端口号之间的映射。一旦NAT转换表项设置完毕,来自任何源地址和端口号的对外部地址和端口号的入站流量都允许并进行转换。
限制性NAT:一种NAT,其中NAT转换表项存储内部地址和端口号与外部地址和端口号之间的映射,可以是特定的源地址或特定的源地址和端口号。对于符合外部目的地址和端口号的NAT转换表项的未知外部地址或端口号的入站数据包将被静默丢弃。
对称NAT:一种NAT,在出站流量中根据外部目标地址将相同的内部地址和端口号映射到不同的外部地址和端口。
你的洞穿方法适用于锥形NAT和地址限制性NAT,但不适用于端口限制性NAT或对称NAT(这可能是你的情况下的NAT)。

谢谢你的好回答。但是,还有一个问题:“如何解决我遇到的对称NAT问题?”而且我很好奇像Viber、WhatsApp这样的聊天应用程序如何在NAT设备后发送消息? - M.Zebeleh
最简单的方法是让应用程序发起与服务器(不在NAT后面)的连接,并始终保持该连接处于打开状态。然后,使用该连接进行所有消息传递(实质上通过服务器中继所有消息)。因此,最简单的方法就是通过编写客户端-服务器应用程序来避免整个问题,而不是编写点对点应用程序。 - Malt
谢谢你的帮助。我解决了问题会通知你的。 - M.Zebeleh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接