2012-01-26 12 views
6

Próbuję asynchronicznie skanować porty TCP. Ponieważ otwarte porty zajmują tylko kilka setnych milisekund, są w porządku, ale kiedy porty są zamknięte, muszę poczekać na odpowiedź.Jak przyspieszyć proces skanowania portów TCP?

Co się dzieje, to że uruchamiam aplikację i prawie od razu widzę port 80, który jest otwarty. Potem muszę poczekać pół minuty, aż wszystkie pozostałe porty zostaną przeskanowane.

EDYCJA. plus Chciałbym pokazać odpowiedź tak, jak to się dzieje, bez oczekiwania na sprawdzenie innych portów.

Jak zrobić to szybciej?

private void btnStart_Click(object sender, EventArgs e) 
{ 
    for (int port = 79; port < 90; port++) 
    { 
     ScanPort(port); 
    } 
} 

private void ScanPort(int port) 
{ 
    TcpClient client = new TcpClient(); 
    client.BeginConnect(IPAddress.Parse("74.125.226.84"), port, new AsyncCallback(CallBack), client); 
} 

private void CallBack(IAsyncResult result) 
{ 
    bool connected = false; 

    using (TcpClient client = (TcpClient)result.AsyncState) 
    { 
     try 
     { 
      client.EndConnect(result); 
      connected = client.Connected; 
     } 
     catch (SocketException) 
     { 
     } 
    } 

    if (connected) 
    { 
     this.Invoke((MethodInvoker)delegate 
     { 
      txtDisplay.Text += "open2" + Environment.NewLine; 
     }); 
    } 
    else 
    { 
     this.Invoke((MethodInvoker)delegate 
     { 
      txtDisplay.Text += "closed2" + Environment.NewLine; 
     }); 
    } 
} 
+0

są one niemal jednocześnie otwierane, ale dopóki nie zostanie osiągnięty limit czasu, nieaktywne porty blokują się. dlatego otwarte porty natychmiast zwrócą "open2", a zamknięte porty zaczekają, aż osiągnie się limit czasu. – Matten

+0

@Matten, ja też nie rozumiem, dlaczego zamknięte porty są wyświetlane prawie w tym samym czasie. – NewHelpNeeder

+3

@NewHelpNeeder: Nie są "zamykane". W rzeczywistości są one chronione przez zaporę ogniową, więc nie otrzymujesz komunikatu ICMP dla "Port nieosiągalny", który mówi oprogramowaniu, że port jest zamknięty. Tak więc jedyną wskazówką, którą otrzymasz, jest limit czasu bez odpowiedzi. Ponieważ limit czasu jest taki sam dla wszystkich połączeń i wszystkie połączenia zostały uruchomione jednocześnie, wszystkie czasy wystąpiły jednocześnie. –

Odpowiedz

7

Możesz użyć funkcji WaitHandle BeginConnect, aby tylko czekać tak długo.

using (var tcp = new TcpClient()) 
{ 
    var ar = tcp.BeginConnect(host, port, null, null); 
    using (ar.AsyncWaitHandle) 
    { 
     //Wait 2 seconds for connection. 
     if (ar.AsyncWaitHandle.WaitOne(2000, false)) 
     { 
      try 
      { 
       tcp.EndConnect(ar); 
       //Connect was successful. 
      } 
      catch 
      { 
       //EndConnect threw an exception. 
       //Most likely means the server refused the connection. 
      } 
     } 
     else 
     { 
      //Connection timed out. 
     } 
    } 
} 
+0

Działa dla mnie +1 – Muthukkumaran

+0

Działa również dla mnie :-) – jreichert

Powiązane problemy