为什么我无法使用公共IP地址连接到我的服务器?

3

我有一个服务器程序和一个客户端程序。在开发程序时,为了方便起见,我将服务器和客户端都运行在同一台机器上。服务器使用以下代码开始监听传入连接:

var listener = new TcpListener(IPAddress.Any, 7070);
listener.Start();

客户端使用以下几行代码连接到服务器(简化版):
var client = new TcpClient(AddressFamily.InterNetwork);
client.Connect(IPAddress.Loopback, 7070);

我使用IPAddress.Loopback是因为我在同一台计算机上运行程序。但是,我知道服务器和客户端未来可能不会在同一台计算机上运行,所以我将其从http://icanhazip.com (IPAddress.Parse(...))更改为我的公共IP地址。因此,客户端无法连接到同一台计算机上的服务器,并出现异常No connection could be made because the target machine actively refused it <my public ip:7070>
我尝试禁用防火墙,但仍然无法正常工作。为什么服务器拒绝连接?我不是明确告诉它使用IPAddress.Any来监听所有接口吗?
为什么会出现这种情况,我该如何解决?

所以你的意思是你尝试过执行 client.Connect(<你的公网IP>, 7070),然后就出现了异常?这是我所期望的,除非你在你的路由器上进行了端口转发,并将端口7070映射到了你的计算机。 - adv12
@adv12,所以你是在告诉我是我的路由器拒绝了连接? - foxneSs
你能够连接到公共IP取决于你的路由器/面向互联网的设备,至少你需要一个端口转发规则,而且通常NAT仍然会阻止它正常工作。 - Alex K.
我会尽力以我所理解的方式来解释,但请注意我并不是专家:你的公共IP由你的ISP提供,实际上是你的路由器的地址。路由器对于局域网内计算机的出站连接进行网络地址转换(NAT)。这些请求在互联网上看起来好像都来自同一个IP,而你的路由器根据地址转换表将响应发送到正确的本地计算机。这对于出站流量有效,但对于入站流量则无效。(续在下一条评论中...) - adv12
@adv12请直接回答问题,不要在这里发表评论。我会接受你的答案。谢谢。 - foxneSs
显示剩余3条评论
2个回答

8

以下是我根据问题评论构建的答案:

你的公共IP由你的ISP提供,实际上是你的路由器的地址。 路由器通过网络地址转换(NAT)为您本地网络中的计算机发出的出站连接进行处理。 这些请求在互联网上看起来像它们都来自一个IP,基于地址转换表,您的路由器会将响应发送到正确的本地计算机。这对于出站连接有效,但不适用于入站连接。

如果某些东西尝试从互联网向您的路由器打开TCP连接,则除非您专门将流量转发到本地网络上的特定计算机,否则路由器无法知道它可能尝试连接的本地计算机。 这就是端口转发的作用。 如果您未配置端口转发,路由器会说:“抱歉,我不处理端口7070上的传入请求。”


3

你的开发机器是否在路由器后面?

通过特定的网络协议,通过公共IP地址发送给你的网络流量到达给定端口上的路由器。你的路由器需要知道将此流量内部发送到你的网络上的哪个位置。流量来自于互联网到达你的机器,而你的路由器可能无法或不会将流量转发到你的计算机上。

由于网络地址转换(NAT)和通用即插即用(UPnP)的强大作用,你在日常生活中并没有注意到这一点。简略地说,网络地址转换允许修改流量头以将流量从公共IP路由到网络上实际的机器IP。当传入流量尝试在你的网络上打开一个连接端口时,路由器需要配置以适当地转发该流量。通用即插即用是一种在许多现代路由器上支持的协议,允许软件和设备无需转发端口即可无缝路由流量。

这给你留下了两个选择:

  1. 为开发目的,访问你的路由器并将所需的端口转发到你的开发机器

  2. 对于更健壮的应用程序,特别是如果你将在不同的机器或不同的网络上运行此应用程序,请考虑添加UPnP支持到你的应用程序,同时要了解一些用户可能不支持或未启用UPnP,在这种情况下仍然需要进行端口转发。


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