检查端口是否打开

我似乎找不到任何告诉我路由器中的端口是否打开的东西。 这有可能吗?

我现在的代码似乎并没有真正起作用……

private void ScanPort() { string hostname = "localhost"; int portno = 9081; IPAddress ipa = (IPAddress) Dns.GetHostAddresses(hostname)[0]; try { System.Net.Sockets.Socket sock = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); sock.Connect(ipa, portno); if (sock.Connected == true) // Port is in use and connection is successful MessageBox.Show("Port is Closed"); sock.Close(); } catch (System.Net.Sockets.SocketException ex) { if (ex.ErrorCode == 10061) // Port is unused and could not establish connection MessageBox.Show("Port is Open!"); else MessageBox.Show(ex.Message); } } 

试试这个:

 using(TcpClient tcpClient = new TcpClient()) { try { tcpClient.Connect("127.0.0.1", 9081); Console.WriteLine("Port open"); } catch (Exception) { Console.WriteLine("Port closed"); } } 

您应该将127.0.0.1更改为192.168.0.1或路由器的IP地址。

一个更好的解决方案,您甚至可以指定超时:

 bool IsPortOpen(string host, int port, TimeSpan timeout) { try { using(var client = new TcpClient()) { var result = client.BeginConnect(host, port, null, null); var success = result.AsyncWaitHandle.WaitOne(timeout); if (!success) { return false; } client.EndConnect(result); } } catch { return false; } return true; } 

并且,在F#中:

 let IsPortOpen (host: string, port: int, timeout: TimeSpan): bool = let canConnect = try use client = new TcpClient() let result = client.BeginConnect(host, port, null, null) let success = result.AsyncWaitHandle.WaitOne(timeout) match success with | false -> false | true -> client.EndConnect(result) true with | _ -> (); false canConnect 

如果你要连接到环回适配器 – localhost127.0.0.1 ( 没有像127.0.0.1这样的地方! ),你就不可能再去路由器了。 操作系统很聪明,可以识别出它是一个特殊的地址。 如果您确实指定了机器的“真实”IP地址,那么Dunno也是如此。

另请参阅此问题: Microsoft环回适配器的用途是什么?

另请注意,运行traceroute localhost (Windows中的tracert localhost )表明所涉及的唯一网络节点是您自己的计算机。 路由器永远不会涉及。

无法知道端口是否在路由器中转发,除非该端口中有程序侦听。

正如您在Clinton中看到的那样,正在使用的.Net类是TcpClient,这是因为您正在使用TCP套接字进行连接。 这就是操作系统建立连接的方式:使用套接字。 但是,路由器只是将数据包(OSI模型的第3层)转发或转出。 在你的情况下,你的路由器正在做什么叫做:NAT。 它是由一个或多个私有IP共享的一个公共IP。 这就是你进行端口转发的原因。

数据包路径中可能有很多路由器,你永远不会知道发生了什么。

假设您正在以传统方式发送信件。 也许你可以在信中写下接收者必须回答你的信,以便检查他/她是否在那里(你和接收者是sockets)。 如果您收到答案,您将确定他/她在那里,但如果您没有收到任何东西,您不知道邮递员(在您的情况下是路由器)是否忘记发送信件,或接收器没有回答。 你也永远不知道邮递员是否已经要求朋友发送那封信。 此外,邮件员不会打开信件,以便知道他/她可能会回答,因为您正在等待回复。 你所要做的就是等一段时间才能收到答案。 如果你在那个时期没有收到任何东西,你会认为接收者不是你发的信。 这是一个“超时”。

我看到了一个提到nmap软件的答案。 这真的是一个非常好的和复杂的软,但我认为它将以相同的方式工作。 如果该端口没有应用程序侦听,则无法知道它是否已打开。

如果我很清楚,请告诉我。

路由器上的前向端口无法从LAN内部进行测试,您需要从WAN(Internet)端连接以查看端口转发是否正常。

一些互联网站点提供服务来检查端口是否打开:

什么是我的IP端口扫描仪

GRC | ShieldsUP!

如果要使用自己的代码进行检查,则需要确保通过外部代理重新路由TCP / IP连接或设置隧道。 这与您的代码无关,它是基本的网络101。

 public static bool PortInUse(int port) { bool inUse = false; IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties(); IPEndPoint [] ipEndPoints = ipProperties.GetActiveTcpListeners(); foreach(IPEndPoint endPoint in ipEndPoints) { if(endPoint.Port == port) { inUse = true; break; } } return inUse; } 

对我来说,在端口连接可用或经过一定程度的重试之后,我需要阻塞一些东西。 所以,我想出了这段代码:

 public bool IsPortOpen(string host, int port, int timeout, int retry) { var retryCount = 0; while (retryCount < retry) { if (retryCount > 0) Thread.Sleep(timeout); try { using (var client = new TcpClient()) { var result = client.BeginConnect(host, port, null, null); var success = result.AsyncWaitHandle.WaitOne(timeout); if (success) return true; client.EndConnect(result); } } catch { // ignored } finally { retryCount++; } } return false; } 

希望这可以帮助!