8

我需要建立从我家的计算机到我的办公室计算机的 tcp 连接。

在办公室有一个路由器,连接了几台计算机。该路由器有互联网,因此连接到该路由器的所有计算机也有互联网。在我的家里,我有一台可以上网的电脑。我需要我的办公室计算机充当服务器,而我的家用计算机则需要连接到它。以前,我曾经能够通过服务器上的端口转发流量进行连接:

    NATUPNPLib.UPnPNATClass upnpnat;
    NATUPNPLib.IStaticPortMappingCollection mappings;

    public ServerExample()
    {
        InitializeComponent();

        upnpnat = new NATUPNPLib.UPnPNATClass();
        mappings = upnpnat.StaticPortMappingCollection;

        //                           server local IP address
        mappings.Add(1300, "TCP", 1300, "192.168.150.146", true, "plsease work");
        // this code tels the router to forward all tcp traffic comming from port
        // 1300 to the server computer (it's lan ip address happens to be 192.168.150.146)
        //...

我能够从我家连接。(我知道简单的方法是打开办公室路由器上的端口并将它们转发到我的电脑问题是我无法访问办公室路由器)

现在他们用更新的路由器替换了我办公室的路由器,我无法使用我的代码。现在,使用新路由器,当我执行 privious 代码时,我得到:

在此处输入图像描述

请注意,映射返回 null;因此,我无法添加映射。

我确信应该有一种方法来建立连接,因为办公室里的一些人使用例如石灰线或比特洪流。我认为我的问题可能与权限有关?我该如何解决这个问题?


编辑

所以从研究中我发现我想做的是“UDP打孔进入防火墙”。我实际上想通过 tcp 连接来完成。我不知道 tcp 和 upd puch holing 之间有什么区别……我的意思是,这样做的目的是让客户端能够找到梨,而无需在路由器上进行配置。

.

.

.

.

.

.

更新

好的,所以我相信我已经尝试过用 c# 做你们在这个问题上发布的内容:好的,让我告诉你我做了什么:

请注意,您可能需要参考此图才能理解我将要解释的内容: 在此处输入图像描述

如您所知,我想在计算机 A 和计算机 B 之间建立 tcp 连接。我设法做到这一点的方法是执行所谓的 tcp 打孔。

第 1 步:我做的第一件事是开始监听服务器 S 上的新连接。

                   TcpListener server = new TcpListener(System.Net.IPAddress.Parse(“192.168.11.109”), 55550);
                   Server.Start();

                   var client = server.AcceptSocket();  \\ wait here until someone connects

第 2 步:现在使用计算机 A 连接到服务器,如下所示:

          TcpClient tcpClient = new TcpClient("192.168.11.109", 55550);

第 3 步:在计算机 A 上执行第 2 步代码后,服务器 S 调试应如下所示:

在此处输入图像描述

第 4 步:现在我们的目标是从计算机 B 连接到计算机 A。服务器 S 拥有 B 建立连接所需的信息。实际上,我必须在计算机 B 和服务器 S 之间建立连接,以便服务器 S 可以为 B 提供适当的参数,以便 B 连接到 A。

第 5 步:因为我正在调试,所以我现在可以通过侦听端口 3313 使计算机 A 成为服务器。我希望计算机 A 现在在该端口(3313)上侦听,因为所有包都发送到路由器端口 3313 的 X 应发送到计算机 A。

       \\ COMPUTER A 
       TcpListener server = new TcpListener(System.Net.IPAddress.Parse("192.168.0.120"), 3313);
        server.Start();

        var newClient = server.AcceptSocket();  \\ wait here until a client gets connected

第 6 步:所以计算机 A 现在应该在端口 3313 上侦听新连接。再次,端口 3313 很重要,因为路由器 x 应该将从该端口接收到的所有包转发到计算机 A。

计算机 A 正在等待新的连接。 在此处输入图像描述

第7步:所以现在快!我们想从计算机 B 建立连接。实际上,服务器 S 将传递参数,但由于我只是想完成这项工作,我将在计算机 B 上快速编写程序。

          TcpClient tcpClient = new TcpClient(“192.168.11.108”, 3313);
           \\192.168.11.108  is the address of router X

最后:

由于某种原因,计算机 B 无法连接到计算机 A。

在此处输入图像描述

它无法连接的原因是因为路由器 X 没有将包转发到计算机 A。(我知道这一点是因为我在路由器 X 上的端口 54540 上启用了端口转发,并且当我使用该端口时它可以工作)我的意思是我不明白为什么路由器 X 没有将来自端口 3313 的流量转发到计算机 A。计算机 A 已经与服务器 S 建立了连接,并且服务器 S 通过端口 3313 发送到路由器 X 的所有内容都发送到了计算机 A。为什么如果我通过端口 3313 将包发送到路由器 X,它们不会被计算机 A 接收!?

PS:

请注意,我在这里展示的所有内容,实际上都有三个路由器 X、Y 和 Z,还有服务器 S、计算机 A 和计算机 B:

在此处输入图像描述

4

4 回答 4

4

TCP hole punching frequently doesn't work. You're best bet is to stick to UDP hole punching. If you need TCP-like behavior, you can use RDP or a similar protocol that gives you TCP behavior but can use UDP as its transport.

The other approach is to relay all traffic through the server. Each host can connect to the server and the server can copy traffic from one connection to the other.

The best solution would be if you can get some support from the routers such as port forwarding or UPnP.

于 2011-09-05T19:42:25.740 回答
4

您的新工作路由器可能已被UPnP禁用,因此您的引用为空。

如果没有这个,您的服务器将无法对入站流量可见,因为路由器不知道将入站数据包发送到哪里。在这种情况下,路由器充当防火墙,阻止传入服务器的流量。

解决这个问题的基本方法是:

1)打开UPnP

这使您的应用程序能够指示路由器如何将入站流量转发回您的服务器。

2)设置端口转发

如上通过手动配置路由器。

3)使您的工作服务器成为客户端

路由器通过允许出站连接来启动连接来工作。它会记住返回地址,重写外部可见的 IP,并为外部流量提供一个未使用的端口以在 (NAT) 上进行对话。这允许出站请求与外部建立通信并绕过防火墙。如果您的家庭 IP 是固定的,您可以在工作中设置一个客户端,尝试按计划呼叫家庭(直到您启动服务器并可以建立连接)。

4)使用P2P(中介服务器)

我不确定你会从哪里开始,但原则是这样的。它通常在单个 UDP 端口上工作。不位于 NAT 之后的服务器用于建立连接。客户端通过 UDP 数据包将其 IP 发送到服务器,路由器使用路由器返回地址重写 UDP 标头。服务器获取此数据并将其发送给其他对等方。现在每个人都知道彼此的返回地址,他们可以直接向彼此发送 TCP 流量,而服务器则让路。

这里有一些关于 NAT 基础知识的非常好的文章,用简单的术语解释。还有一篇很好的文章解释了 P2P 如何利用 NAT 绕过防火墙。

希望这能给你一些想法。

于 2011-09-04T00:38:01.020 回答
2

有一篇关于 UDP 和 TCP 打孔技术的优秀文章。

http://www.brynosaurus.com/pub/net/p2pnat/

但是,对于这种打孔技术,您需要一个知名的集合服务器,我认为您不想设置它。

顺便说一句,您需要仔细检查公司关于在办公室拥有自己的服务器的政策。出于安全考虑,我认为公司不允许员工在内部设置自己的服务器。

于 2011-09-04T07:54:40.063 回答
2

您可以编写自己的代理:

服务器:在 1300 上侦听来自 A 的连接,在 1301 上侦听来自 B 的连接。保留两个连接的列表,当每个连接至少有一个时,创建一个代理对象。此时,您从 B 向您的连接发出信号,表明您有一个连接,这可能是一个信号字节或一个端口,甚至是要连接的地址。之后,当您从 A 获取数据时,将其发送给 B。当您从 B 获取数据时,将其发送给 A。

计算机 B:程序保持与服务器上端口 1301 的连接。如果连接断开,请重新建立连接。当您收到一个信号(可能有地址和端口或者只是一个“我有一个连接”字节)时,创建一个到所需端口的连接并将这两个连接存储在一个代理对象中。当您从一个接收数据时,将其发送给另一个。由于您正在使用该连接,请在服务器上建立一个到端口 1301 的新连接以处理更多。

当然,您必须处理断开的连接,在 B 和服务器之间始终打开的挂起连接之间发送保持活动信号会有所帮助。

这是我很久以前编写的用于代理的示例类。我没有时间清理它,但是如果您看到 TcpProxy 是接受连接的父类,则 Client 是接受的连接,而 RemoteEndPoint 是要连接的端点。它还将数据写入文件并执行一些您可以忽略的其他事情。

于 2011-09-06T21:12:00.267 回答