# Ping mehrerer Ports aus int[] ohne for-Schleifendurchlauf



## MAGIo (16. Mai 2011)

Hallo, 

ich habe folgendes Problem, in meinem Programm (bestehend aus einem IP Mapper und verschiedenen Unterprogrammen), habe ich neuerdings zur besseren Analyse eine externe Hilfsklasse eingebaut, die ich im Netz gefunden habe und etwas abändern wollte. 

Es soll eigentlich nur "pingen", mittels JAVA Boardmitteln, daher werden auch die Zeiten der Sockets gemessen und genutzt. Für bestimmte Geräte im LAN, wie zB einer Xbox360, gibt es nur die Möglichkeit dies auf einem bestimmten Port auszuüben (1026)usw...

Ursprünglich war diese Klasse nur für einen CHECKPORT = 80 gedacht und mehrere Abfragen mittels entsprechenden Aufrufen. Nun wollte ich ein Array erstellen mit den zu benutzenden Ports und diese mittels Zählschleife für _ aufrufen, doch leider klappt das alles nicht so wie ich will. 

Ich habe schon die Klammern variiert, zig neue Variationen probiert mit Deklarierungen, doch irgendwie entferne ich mich immer weiter vom Ziel. Hoffe Ihr könnt mir helfen,

Hier der Code:



		Java:In die Zwischenablage kopieren


import java.io.IOException;
import java.net.ConnectException;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * Einfache Hilfsklasse zum ermitteln ob ein Host online ist
 * @author achristian
 *
 */
public class CheckIP
{
	public int [] CHECKPORT;
	public boolean DEBUG = false;
	/**
	 * Prüft ob ein Host erreichbar ist. 
	 * Achtung: Wenn der Host eine Firewall-Einstellung 
	 * hat die unzulässige-Portanfragen "dropped" dann 
	 * wird der Online-Status des Host nicht erkannt.
	 * 
	 * Ist der Port am Host offen erhält man einen 
	 * repräsentativen Zeitwert in Millisekunden für den 
	 * Verbindungsaufbau (ähnlich der Ping-Zeit).
	 * 
	 * Ist der Port nicht offen liegt die ermittelte Zeit 
	 * meist um 1000ms.
	 * 
	 * Wird die Portanfrage gedropped oder ist der Host
	 * nicht online erhält man -1
	 *  
	 * @param host der getestet werden soll
	 * @return Zeit in Millisekunden
	 */
		public int isReachable(String host)
		{
		CHECKPORT = new int[2];	
		int[] CHECKPORT = {80, 1026, 1026};
		long start = System.currentTimeMillis();	
			{   
				for (int i=0; i<=2; i++)	
				try
				{
					Socket socket = new Socket(host,CHECKPORT[i]);
					socket.close();
				}//try			
				catch(ConnectException e)
				{
					String ex = e.toString();
					if (ex.contains("Connection refused"))
					{
						long end = System.currentTimeMillis()-start;
						if (DEBUG)
							System.out.println("online, indirekt ermittelt");
						return (int)end;
					}//if (ex.contains..
					else
					{
						if (DEBUG) 	
							System.out.println("offline");
						return -1;
					}//else
				}//catch (ConnectException e)
				catch(UnknownHostException e)
				{	
					if (DEBUG)	
						System.out.println("offline");
					return -1;
				}//catch
				catch (IOException e)
				{
					if (DEBUG)
						System.out.println("offline");
					return -1;							
				}//catch (IOException e)
				long end = System.currentTimeMillis()-start;
    				if (DEBUG)	
    					System.out.println("online");
    				return (int)end;	
			}//for
		}//public int isReachable Method
	public static void main(String[] args)							
	{
		System.out.println(new CheckIP().isReachable("127.0.0.1"));
//		System.out.println(new CheckIP().isReachable("127.0.0.1"));
//		System.out.println(new CheckIP().isReachable("127.0.0.1"));	
	}//main Methode
}//public class CheckIP

_


----------



## HoaX (16. Mai 2011)

"funktioniert nicht" ist keine Fehlerbeschreibung! Drück dich klar aus, dann kann man auch helfen, aber so wird das nix...


----------



## tagedieb (17. Mai 2011)

```
CHECKPORT = new int[2]; 
        int[] CHECKPORT = {80, 1026, 1026};
```

Hier definiertst du eine Instanzvariable der Groesse 2 ohne es zu initialisieren, also 2 mal 0. In der 2ten Zeile erstellst du eine gleichnamige lokale Variable mit 3 Werten und 2 mal 1026.

Entweder laeuft hier etwas gruendlich schief oder es fehlt an aussagekraeftigen Kommentar


----------



## MAGIo (17. Mai 2011)

Oh... da hab ich Euch die falsche Version reinkopiert, ich hatte ja in allen Variationen rumprobiert, richtig sollte es heissen:


```
public int[] CHECKPORT = { 80, 1026, 5060 }
```

Der Fehler ist halt, dass das Programm für den aufgerufenen Host alle 3 Ports durchlaufen soll, also auch 3 Ausgaben machen sollte. Es kommt lediglich -1 raus! Wenn ich hingegen 3 mal denselben Port eintrage als Test, kommt ansatzweise was Richtiges (Pingzeit in ms) raus.


----------



## SlaterB (17. Mai 2011)

Zeile 39 und 79 können derzeit raus, gehören NICHT zur Schleife, die verwirren nur,

ansonsten hast du bei jedem catch ein return eingebaut, wann immer also eine Exception auftritt, was bei dir ja auch als legitimer Test gilt,
wird die Schleife und die Methode beendet, ist doch verständlich?
hast du überhaupt DEBUG eingeschaltet um ein Minimum an Ausgaben zu sehen? noch besser die Exceptions ausgeben,

hier noch ein Beispielprogramm, welches gleich selber einen Server aufmacht:

```
public class Test
{
    public boolean DEBUG = true;

    public int isReachable(String host)
        throws Exception
    {
        System.out.println("start");
        int[] CHECKPORT =
            {4000, 4001, 4002};
        long start = System.currentTimeMillis();
        for (int i = 0; i <= 2; i++)
        {
            Thread.sleep(500);
            System.out.println("i: " + i);
            try
            {
                Socket socket = new Socket(host, CHECKPORT[i]);
                socket.close();
            }// try
            catch (ConnectException e)
            {
                String ex = e.toString();
                System.out.println("ex: " + ex);
                if (ex.contains("Connection refused"))
                {
                    long end = System.currentTimeMillis() - start;
                    if (DEBUG) System.out.println("online, indirekt ermittelt");
                    return (int)end;
                }// if (ex.contains..
                else
                {
                    if (DEBUG) System.out.println("offline");
                    return -1;
                }// else
            }// catch (ConnectException e)
            catch (UnknownHostException e)
            {
                if (DEBUG) System.out.println("offline");
                return -1;
            }// catch
            catch (IOException e)
            {
                if (DEBUG) System.out.println("offline");
                return -1;
            }
        }
        long end = System.currentTimeMillis() - start;
        if (DEBUG) System.out.println("online");
        return (int)end;
    }

    public static void main(String[] args)
        throws Exception
    {
        Runnable r = new Runnable()
            {
                public void run()
                {
                    try
                    {
                        ServerSocket x = new ServerSocket(4000);
                        Socket y = x.accept();
                        System.out.println("accept");
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            };
        new Thread(r).start();

        Thread.sleep(2000);

        System.out.println("time: " + new Test().isReachable("127.0.0.1"));
    }
}
```
beachte die korrekten Schleifen-Klammen..

Ausgabe:

```
start
i: 0
accept
i: 1
ex: java.net.ConnectException: Connection refused: connect
online, indirekt ermittelt
time: 1984
```
für i==0 ohne Fehler ist von dir überhaupt keine Ausgabe vorgesehen,
nach i==1 ist Schluss, i==2 kommt nicht mehr dran


----------



## tagedieb (17. Mai 2011)

Ich habe deine Logik nicht ganz verstanden. Ich denke du willst den Ping des ersten funktionierenden Ports haben.

Also solltest du die Zeit messen vor und nach dem oeffnen des Sockets und nicht die Zeit zum testen aller Ports. 
Der erste funktionierende Port schickt die Ping Zeit zurueck. Im Fehlerfall wird die Exception ignoriert und du pruefst einfach den naechsten Port.
Falls keiner deiner Ports aktiv ist kannst du mittels eines Pseudoports die Zeit messen bis du die Exception geworfen wird.

PS. die Schleifenbedingungn sollte nicht fix definiert sein sondern ueber die Laenge des Portarrays laufen, ansonsten gibts eine IndexOutOfBoundsException wenn du einen Port loeschst oder einen hinzufuegst wird er ignoriert


```
public int isReachable(String host) {
		for (int i = 0; i <= CHECKPORT.length; i++) {
			long start = System.currentTimeMillis();
			try {
				Socket socket = new Socket(host, CHECKPORT[i]);
				socket.close();
				long end = System.currentTimeMillis() - start;
				if (DEBUG)
					System.out.println("online");
				return (int) end;

			}// try
			catch (Exception e) {
				System.out.println(e);
			}
		}

                // kein Port hat funktioniert, messe Zeit fuer ConnectException 
		long start = System.currentTimeMillis();
		try {
			Socket socket = new Socket(host, 0xFFFF);
                        // erwarte Exception
			socket.close();
			long end = System.currentTimeMillis() - start;
			if (DEBUG)
				System.out.println("online");
			return (int) end;

		} catch (ConnectException e) {
			String ex = e.toString();
			if (ex.contains("Connection refused")) {
				long end = System.currentTimeMillis() - start;
				if (DEBUG)
					System.out.println("online, indirekt ermittelt");
				return (int) end;
			}// if (ex.contains..
			else {
				if (DEBUG)
					System.out.println("offline");
				return -1;
			}// else
		}// catch (ConnectException e)
		catch (UnknownHostException e) {
			if (DEBUG)
				System.out.println("offline");
			return -1;
		}// catch
		catch (IOException e) {
			if (DEBUG)
				System.out.println("offline");
			return -1;
		}// catch (IOException e)

	}// public int isReachable Method
```


----------



## MAGIo (17. Mai 2011)

Abgeänderter Code:

```
import java.io.IOException;
import java.net.ConnectException;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * Einfache Hilfsklasse zum ermitteln ob ein Host online ist
 * @author achristian
 *
 */
public class CheckIP
{
	public int [] CHECKPORT = {80, 1026, 1026};
	public boolean DEBUG = true;
	/**
	 * Prüft ob ein Host erreichbar ist. 
	 * Achtung: Wenn der Host eine Firewall-Einstellung 
	 * hat die unzulässige-Portanfragen "dropped" dann 
	 * wird der Online-Status des Host nicht erkannt.
	 * 
	 * Ist der Port am Host offen erhält man einen 
	 * repräsentativen Zeitwert in Millisekunden für den 
	 * Verbindungsaufbau (ähnlich der Ping-Zeit).
	 * 
	 * Ist der Port nicht offen liegt die ermittelte Zeit 
	 * meist um 1000ms.
	 * 
	 * Wird die Portanfrage gedropped oder ist der Host
	 * nicht online erhält man -1
	 *  
	 * @param host der getestet werden soll
	 * @return Zeit in Millisekunden
	 */
		public int isReachable(String host)
		{	
		long start = System.currentTimeMillis();	
//			{   
				for (int i=0; i<=2; i++)	
				try
				{
					Socket socket = new Socket(host,CHECKPORT[i]);
					socket.close();
				}//try			
				catch(ConnectException e)
				{
					String ex = e.toString();
					if (ex.contains("Connection refused"))
					{
						long end = System.currentTimeMillis()-start;
						if (DEBUG)
							System.out.println("online, indirekt ermittelt");
						return (int)end;
					}//if (ex.contains..
					else
					{
						if (DEBUG) 	
							System.out.println("offline");
						return -1;
					}//else
				}//catch (ConnectException e)
				catch(UnknownHostException e)
				{	
					if (DEBUG)	
						System.out.println("offline");
					return -1;
				}//catch
				catch (IOException e)
				{
					if (DEBUG)
						System.out.println("offline");
					return -1;							
				}//catch (IOException e)
				long end = System.currentTimeMillis()-start;
    				if (DEBUG)	
    					System.out.println("online");
    				return (int)end;	
//			}//for
		}//public int isReachable Method
	public static void main(String[] args)							
	{
		System.out.println(new CheckIP().isReachable("127.0.0.1"));
//		System.out.println(new CheckIP().isReachable("127.0.0.1"));
//		System.out.println(new CheckIP().isReachable("127.0.0.1"));	
	}//main Methode
}//public class CheckIP
```

Hier die DEBUG Ausgabe:



> offline
> -1



Ich habe mal die Schleifenumklammerung abgeändert und hinter die Zählschleife bzw. am Ende des Codes gesetzt. Nun erhalten ich beim Methodenaufruf in Zeile 34: folgenden Fehler:
This method must return a result of type int


----------



## MAGIo (17. Mai 2011)

Nein nein nein...

Es soll nicht der erste funktionierende Port angezeigt werden, sondern alle 3 Ports für die jeweilige IP durchlaufen und ausgegeben werden um überhaupt zu pingen. Natürlich wäre der erste funktionierende Port auch richtig, aber soweit wollte ich gar nicht gehen.


----------



## tagedieb (17. Mai 2011)

???:L

Was willst du den nun genau angezeigt haben??

Die Gesamtzeit zum Pingen aller 3 Ports? Oder die Zeit zum Pingen jedes einzelnen Ports?


----------



## MAGIo (17. Mai 2011)

Jedes Einzelnen eigtl. 

Aber Du hast Recht, es ist besser einen Ausdruck auszugeben, sobald einer der 3 Ports funktioniert je getestete IP.


----------



## SlaterB (17. Mai 2011)

MAGIo hat gesagt.:


> Ich habe mal die Schleifenumklammerung abgeändert und hinter die Zählschleife bzw. am Ende des Codes gesetzt. Nun erhalten ich beim Methodenaufruf in Zeile 34: folgenden Fehler:
> This method must return a result of type int


schau dir meinen Code an wie es richtig geht, 
wenn du das letzte return dagegen in die Schleife ziehst,  dann hat das zwei im Grunde triviale Folgen, 
die solltest du eigentlich selber sehen können..., keine Minute Luft geholt und nachgedacht?

1. am Ende des ersten Schleifendurchlaufs ist garantiert Ende, weil da ja ein return steht, wieso überhaupt eine Schleife?
2. der Compiler ist nicht unbedingt schlau genug zu wissen, dass die Schleife garantiert begonnen wird
(und dann wegen 1. garantiert ein return folgt),
deshalb denkt Java dass auch der Code nach der Schleife noch drankommt, da fehlt das return, wie soll die Methode dort enden, welcher Rückgabewert?


----------



## MAGIo (17. Mai 2011)

Funktioniert perfekt, DANKE!


----------

