2012-08-06 144 views
14

我似乎无法找到任何告诉我路由器中的端口是否打开的信息。 这甚至可能吗?检查端口是否打开

的代码,我现在并没有真正似乎工作...

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); 
    } 
} 
+0

它是如何失败?结果不符合你的预期,你是否得到例外? – TheEvilPenguin 2012-08-07 00:08:18

+0

如果你的代码连接到端口,它应该说端口是开放的不关闭 – 2012-08-07 00:26:30

+0

@TheEvilPenguin我想说我的端口是开放的,因为我在我的路由器转发它,但它没有连接... – 2012-08-07 00:30:26

回答

23

试试这个:

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地址是什么。

+0

它仍然不会如果我使用192.168.1.1 – 2012-08-07 00:45:21

+0

当您尝试使用代码时会发生什么? – 2012-08-07 01:56:53

+0

它说它即使端口打开也不能连接。 – 2012-08-07 14:12:31

2

如果要连接到loopback adapterlocalhost127.0.0.1there's no place like 127.0.0.1!),你不可能永远走出去到路由器。操作系统足够聪明,可以识别出它是一个特殊的地址。如果你确实指定了你的机器的“真实”IP地址,那么也不要这样。

也看到这个问题:What is the purpose of the Microsoft Loopback Adapter?

还要注意的是(在Windows tracert localhost)运行traceroute localhost显示,涉及的唯一网络节点是你自己的机器。路由器从不涉及。

1

无法从局域网内测试路由器上的端口转发,您需要从WAN(互联网)端连接以查看端口转发是否正常工作。

几个互联网网站提供的服务来检查如果一个端口是开放的:

What's My IP Port Scanner

GRC | ShieldsUP!

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

12

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

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 
+0

这种方法的性能如何?特别是在F#中?我正在为网络协议撰写论文,部分(预)流程是编写可用端口列表。 – czifro 2016-10-23 19:41:08

+0

它应该像C#一样性能...但自己衡量它以防万一? – ympostor 2016-11-08 05:00:38

+0

这个模式可以用于System.Net.Sockets.UdpClient吗? – tatmanblue 2016-12-21 23:01:37

2

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

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

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

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

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

请让我知道我是否清楚。