IP Scanner via Sockets [Problem]

Boehrsi

Grünschnabel
Hi,
ich habe einen Problem bei einem kleinen Projekt welches ich gerade schreibe. Es geht um einen IP Scanner fürs LAN, der Teil eines kleinen Netzwerktools ist.
Ich versuche via Sockets eine bestimmte IP Range abzufragen (256 Adressen, der User muss z.B. 100.100.100, als Grundnetz angeben und folgend werden dann 100.100.100.1, 100.100.100.2 etc. geprüft).
Wenn ich das ganze Teste für z.B. 10 IPs mit Socket Timeout 100 findet er die IPs manchmal, aber auch nicht immer, wenn ich nun aber für 20,30 oder gar 256 den Test ausführe schlagen leider alle Versuche fehl.
Mit einem Timeout von 1000 scheint es zu gehen, aber für einen IP Scan 4 Min. 30 Sek. warten möchte wohl keiner.
Deswegen hier die Frage, kennt jemand das Problem oder noch besser, gibt es eine Lösung?
Ich will das ganze nicht in 2 Sekunden fertig haben, das es etwas dauert mit den Sockets ist kein Problem, nur fast 5 Minuten ist etwas übertrieben.

Code:
//host entspricht z.b. 100.100.100. und hostpart2 ist dann der Index der in der Schleife hochgezählt wird.
String host2 = host + hostpart2;

SocketAddress  sa=new InetSocketAddress(host2,port);
Socket clientSocket = null;
clientSocket = new Socket();
try {	
clientSocket.connect(sa,100);	
clientSocket.close();	
System.out.println(host2);
}
catch (IOException e) {			
}
hostpart2++;
 
Zuletzt bearbeitet:
Hi das ist die Fehlermeldung:


java.net.SocketTimeoutException: connect timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(Unknown Source)
at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at Computers$1.run(Computers.java:35) // In der Zeile 35 steht der socket connect -> clientSocket.connect(sa,100);
at java.lang.Thread.run(Unknown Source)

Und in "langsam" oder mit wenigen eingaben kommt halt keine. Java scheint mit den Sockets nicht schnell genug hinterher zu kommen, wenn ich alles in eigene für sich laufende Threads packe, könnte es dann besser werden?
 
Hallo,

da mich dieses Thema auch interessiert, möchte ich mal den aktuellen Status meiner "Ermittlungen" ( :rtfm: ) posten.
Im übrigen ist dies nicht der einzige Thread über dieses Thema im Forum, der nicht beendet wurde, nur um darauf hin zu weisen ^^ lol
-> http://www.tutorials.de/forum/java/176845-socket-timeout.html

Aber zum Thema:
Da Java selbst kein icmp also, SOCKET_RAW ünterstützt, wird es schwer sein, wenn nicht unmöglich, ein PING-Programm in Java zu schreiben, das möglichst unabhängig vom Betriebssystem funktioniert.

Mit derzeitigen Java-Klassen und Methoden, braucht man zumindest den Port zu der IP und dann muss man davon ausgehen, dass dieser vielleicht gesperrt ist.

Wenn man nicht an eine Sprache oder ein Betriebssystem gebunden ist, würde ich hier zu C-Sharp (Class Ping ^^) oder ähnliches raten.

MfG
 
Jo, erstmal danke für die Antwort. Ich habe das ganze jetzt mit ein bissel rumtesten so hinbekommen, dass ich in 2 Minuten 256 IPs gecheckted bekomme. Aber leider ist das halt nicht zu 100% sicher und jo mit geblockten Port funtzt das natürlich nicht. Ich versuche über 445 eine Verbindung aufzubauen.

Mal schauen, vielleicht mache ich es so das ichs wirklich nur für Windows schreibe, dann könnte ich auch dort die vorhandenen Sachen nutzen.
 
genau, das wäre die optimale Lösung,

hab hier auch noch code zur Verfügung, vielleicht hilft es Dir

Java:
import java.net.InetAddress;
import java.net.Socket;


public class PingNative
{
  public static void main( String[] args )
  {
      // funktioniert auch mit ip's
      String hostip = "boehrsi.net";
      int port = 80;
      
      Object[] e;
      if((e = ping(hostip, port)) != null)
      {
          System.out.println("HostIP: " + e[0] + "\n" +
                               "HostName: " + e[1] + "\n" + 
                               "MilliSeconds: " + e[2]);
      }
      else
      {
          System.out.println("No Response");
      }
  }
  
  public static Object[] ping(String hostip, int port)
  {
      try 
        {
            long roundTripTime = System.nanoTime();
            InetAddress host = InetAddress.getByName(hostip);
            
            Socket sock = new Socket(host, port);
            roundTripTime = (System.nanoTime() - roundTripTime) / 1000000L;
            sock.close();
            return (new Object[]{host.getHostAddress(), host.getHostName(), roundTripTime});
        } 
        catch(Exception e) 
        {
            System.out.println(e.getMessage());
            return null;
        }
  }
}


MfG
 
Hier mein Vorschlag zum Scannen des Netzwerkes aucho hne Sockets(Arbeitet über das Windows bzw. das Samba-Netzwerk):
(kA ob das Windowsnetzwerk Samba heißt. Jedenfalls unter Linux heißen die Tools, die mit dem Windows-Netzwerk arbeiten, Samba :D)

Java:
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;

public class LanScanner {
	private static final int TIMEOUT = 15000;

	public static void main(String[] args) {
		try {
			Enumeration<NetworkInterface> enumInterfaces = NetworkInterface.getNetworkInterfaces();
			while (enumInterfaces.hasMoreElements()) {
				NetworkInterface currentInterface = enumInterfaces.nextElement();
				if (currentInterface.isLoopback() == false && currentInterface.isUp()) {
					Enumeration<InetAddress> enumAdresses = currentInterface.getInetAddresses();
					while (enumAdresses.hasMoreElements()) {
						InetAddress currentAddress = enumAdresses.nextElement();
						new LanScanner(currentAddress);
					}
				}
			}
			// Wenn man davon ausgeht, dass nur eine Netzwerkkarte aktiv ist, dann nehmen wir die Kurzfassung:
			// new LanScanner(InetAddress.getLocalHost());
		} catch (SocketException e) {
			e.printStackTrace();
		}
	}

	private LanScanner(InetAddress ia) {
		String[] sAddress = ia.getHostAddress().split("[.]");
		String lanAddress = sAddress[0] + "." + sAddress[1] + "." + sAddress[2] + ".";
		for (short s = 1; s < 255; s++) {
			new AddressScanner(lanAddress + s);
		}
	}

	private class AddressScanner implements Runnable {
		private String sInetAddress = null;

		private AddressScanner(String inetAddress) {
			this.sInetAddress = inetAddress;
			new Thread(this).start();
		}

		public void run() {
			try {
				InetAddress ia = InetAddress.getByName(this.sInetAddress);
				if(ia.isReachable(TIMEOUT) || !ia.getCanonicalHostName().equalsIgnoreCase(this.sInetAddress) || !ia.getHostName().equalsIgnoreCase(this.sInetAddress)) {
					System.out.println("Reached " + this.sInetAddress + "(" + ia.getCanonicalHostName() + ")");
				}
			} catch (UnknownHostException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

Die if-Bedinung
Java:
if(ia.isReachable(TIMEOUT) || !ia.getCanonicalHostName().equalsIgnoreCase(this.sInetAddress) || !ia.getHostName().equalsIgnoreCase(this.sInetAddress))
ist deshalb so eigenartig, da die Funktionen über das Betriebsystem laufen. Und jeder kenn Windoof.. es macht was es will.
Es kann also sein, dass, obwohl die Funktion "isReachable(timeout)" ein false zurückgibt nachdem der Timeout erreicht worden ist (ihr kennt das ja wenn ihr die Netzwerkumgebung öffnet und er PC teilweise Jahrunderte lang sucht), der Name des Rechners der dazugehörigen IP aufgelöst werden kann. Demnach existiert er also auch im Netzwerk. Alternativ könnt ihr natürlich auch den TIMEOUT-Wert hochdrehn. Aber so wie das Programm da steht funktioniert es bei mir einwandfrei.
 
Zuletzt bearbeitet:
Danke für die Tipps :), habe das ganze einfach mit der Windows ping.exe gemacht. Klappt gut und wenns eh nur für Windows sein soll, warum nicht.

Allerdings gibts halt beim parsen Probleme mit den verschiedenen Windows Versionen, deswegen teste ich eure Vorschläge nochmal genauer.
 

Neue Beiträge

Zurück