2012-08-06 184 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軟件的答案。這真的是一個非常好的和複雜的軟件,但我認爲它會以同樣的方式工作。如果沒有應用程序在該端口中偵聽,則無法知道該應用程序是否處於打開狀態。

請讓我知道我是否清楚。