# Rückgabewert bei Run()-Methode



## jojo.14 (5. Okt 2012)

Hallo zusammen,

ich habe folgende Frage. Das Programm scannt einen Port auf einem Zielhost. Das Scan-Pogramm wird durch die Run()-Methode ausgeführt. Meine Frage ist, wie kann ich beim Verwenden der Run()-Methode  trotzdem einen Rückgabewert generieren. In der Methode "run" ist kein Rückgabewert vorgesehen. 


```
public class Portscanner implements Runnable {
	
	//Variablen-Deklaration------------------------------------------------------------------------
	int port;		//Integer mit Portnummer 
	String host;	//String aus anderer Klasse mit IP-Adresse
	static boolean scannenerfolgreich = false;
	
	
	//Portscanner übernimmt Werte-------------------------------------------------------------------
	public Portscanner(String host, int port) {
		//Zuweisen der oben übernommenen Variablen
		this.port = port;
		this.host = host;
	}

	
	//Aufrufen der Run-Methode----------------------------------------------------------------------
	public void run() {
		try {
			//Es wird versucht eine TCP-Verbindung aufzubauen
			Socket ziel = new Socket(host, port);
			System.err.println("Verbunden mit " + host + " auf Port " + port);
				
				
			scannenerfolgreich = true;
			//Soll eigentlich zurückgegeben werden!?!? 
				
			ziel.close();
				
		//Wenn die Verbindung fehlschlägt gebe folgende Meldungen aus
		} catch (UnknownHostException e) {
			System.out.println("Der Host " +host+ " ist unbekannt");
			//scannenerfolgreich = false;
		} catch (IOException e) {
			System.out.println("Den Port " +port+ " auf Zielhost nicht erreicht");
			//scannenerfolgreich = false;  
		}
		
	}//Run zu
```

Es reicht mir eine boolean-Variable (true,false) zurückzugeben, die ich dann weiter verwende. Diese soll mir nur sagen, ob ich den Port auf dem Zielhost erreicht habe oder nicht. Muss diese Information weiterverwenden.


Vielen Dank schon mal 

Gruß Joe


----------



## SlaterB (5. Okt 2012)

Gegenfrage: wer sollte diesen Rückgabewert bekommen?
wenn du Runnable als Thread benutzt, Thread mit start() gestartet, dann bist du selber gar nicht an der Stelle,
um mit run() in Berührung zu bekommen,

wenn nicht als Thread, dann ist strenggenommen Interface Runnable/ Methode run() nicht nötig, dann kannst du es designen wie du willst,

oder, um beides gleichzeitig zu haben:

```
public void run() {
   doWork(); // oder run-Methode gar leer lassen
}

public int doWork() {
   ...
   return ..;
}
```
dann kann wer immer lustig ist run() aufrufen, das Interface ist auch zufriedenstellend implementiert,
falls du das Objekt aber anders nutzen willst, rufe direkt doWork() auf und erhalte den Rückgabewert

------

falls du doch einen Thread hast, das ganze nebenläufig läuft, wird es generell komplizierter


----------



## mvitz (5. Okt 2012)

Das geht nicht direkt mit Runnable, aber mit Hilfe von Callable, siehe z.B. https://blogs.oracle.com/CoreJavaTechTips/entry/get_netbeans_6


----------



## nillehammer (5. Okt 2012)

Neben mvitz's Vorschlag wäre es auch denkbar, das Ergebnis in eine Variable zu schreiben, die von woandersher ausgelesen werden kann. In Deinem konkreten Fall wäre eine zentrale Map<Integer,Boolean> zum mappen der Portnummer auf das Scanergebnis sinnvoll.
[EDIT]Sehe gerade, der Host ist auch variabel. D.h. die Map muss etwas anders aussehen, aber das Prinzip dürfte klar sein.[/EDIT]


----------



## jojo.14 (8. Okt 2012)

Hey zusammen 

danke für die zahlreichen Antworten. 

Die Klasse Portscanner wird aus meiner "Hauptklasse" (die auch andre Klassen steuert) mit Hilfe eines Threads aufgerufen. Mit dem Aufruf ThreadABC.start(); ...
Ist also nebenläufig. 

Möchte das Ergebnis:
Ist Port A auf Host A erreichbar, Port B auf Host B erreichbar usw....
in eine Datenbank schreiben und eine Logdatei anlegen. 
Wollte in meiner Klasse "Datenbank" mit der Methode 

einlesen(String Host A, int PortA, String Datum, boolean erreichbar Ja/Nein) angeben können, ob der Port erreichbar war. 

Meine Hauptklasse, die die Abläufe steuert soll dann die Methode Datenbank.einlesen() z.B. alle 10 Minuten aufrufen.

Unten auf der Konsole kann man sich das ja anzeigen lassen ob der Port erreicht wurde oder nicht, aber nicht damit weiterarbeiten.

P.S. Werde morgen mal das callable() testen und schauen, ob mir das weiterhilft. Danke nochmal

Schöne Grüße Joe


----------



## SlaterB (8. Okt 2012)

in jedem Fall wäre dann wie gesagt niemand da, der auf den Rückgabewert hört,
andere Threads gehen nach start() weiter, wie sollen die davon etwas mitbekommen,

wenn sie periodisch nachfragen ist das ein anderer Weg,
wenn der Thread mit der fertigen Zahl aktiv werden soll kann das über neumodischen Kram wie Futures gehen 
oder schlicht am Ende der run-Methode, wo das return stehen würde, irgendwo irgendwas aufrufen, 
so läuft das letzlich immer, egal wie schick die Libraries heißen


----------



## jojo.14 (9. Okt 2012)

Ok,

ich habe mich jetzt mal mit "Callable" , "ExecutorService" , "Future-Objekt" beschäftigt. 

So wie ich das verstehe kann ich statt Runnable -> Callable nutzen. Das Callable macht im Prinzip das Gleiche nur das ich mir Rückgabewerte geben lassen kann.
Allerdings kann das Callable nicht mehr einfach als Threadobjekt mit Thread.start() gestartet werden. Hier soll man den ExecutorService verwenden. Dieser startet das Callable mit der Methode .submit(). Den Rückgabewert aus dem Callable rufe ich mit dem Future-Objekt und der Methode .get() auf.

Werde jetzt mal den Code versuchen so umzuschreiben und schaue, ob das funktioniert.


Danke

Gruß Joe


----------



## jojo.14 (9. Okt 2012)

Ok so weit funktioniert jetzt alles wie ich es vorhatte. Danke nochmal für die schnellen und guten Antworten.

Hier mal mein abschliessender Code:

Auszug aus der Hauptklasse:

```
String host = "localhost";
		int port = "meinPort" ;
		
		Portscanner2 portverbinder2 = new Portscanner2(host, port);
				  
	      ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
	      Future<String> future = singleThreadExecutor.submit(portverbinder2);

		//Abfrage des erfolgreichen Scans------------------------------------------------------------------
		
	    try {
			scan = future.get();			//get blockiert bis das Ergebnis zur Verfügung steht
                                      System.out.println("Scan erfolgreich= " +scan);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
```

Portscannerklasse

```
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.Callable;

public class Portscanner2 implements Callable<String> {

	//Variablen-Deklaration-------------------------------------------------------------------------
		int port;		//Integer mit Portnummer 
		String host;	//String für IP-Adresse
		static String scannenerfolgreich = "nein";
		
		
		//Portscanner übernimmt Werte aus anderer Klasse------------------------------------------------
		public Portscanner2(String host, int port) {
			//Zuweisen der oben übernommenen Variablen
			this.port = port;
			this.host = host;
		}
	
		//Aufrufen der Callable-Methode----------------------------------------------------------------------
		public String call() {
			
			try {
				//Es wird versucht eine TCP-Verbindung aufzubauen
				Socket ziel = new Socket(host, port);
				System.err.println("Verbunden mit " + host + " auf Port " + port);
					
					
				scannenerfolgreich = "ja";
				//Soll eigentlich zurückgegeben werden!?!? 
					
				ziel.close();
					
			//Wenn die Verbindung fehlschlägt gebe folgende Meldungen aus
			} catch (UnknownHostException e) {
				System.out.println("Der Host " +host+ " ist unbekannt");
				scannenerfolgreich = "nein";
			} catch (IOException e) {
				System.out.println("Den Port " +port+ " auf Zielhost nicht erreicht");
				scannenerfolgreich = "nein";  
			}
			
			return scannenerfolgreich;
		
		}//Callable zu	
		
	
}//Klasse zu
```


Gruß Joe


----------



## SlaterB (9. Okt 2012)

steht das so direkt hintereinander?
einen zweiten Thread zu starten und dann nur auf dessen Ergebnis zu warten sieht kontraproduktiv aus,
dann auch einfach die Methode an sich aufrufen, da ist der Aufrufer genauso lange blockiert

mit anderen Code zwischendurch, isDone(), get(timeout) usw. wäre es aber sinnvoll


----------



## jojo.14 (9. Okt 2012)

Bislang wird nur eine Port und ein Host gescannt. Wollte in den nächsten Tagen schauen, wie die Sache sich verkompliziert, wenn ich beispielsweise auf 20 Hosts regelmäßig diesen Port abfrage. 

Werde also noch den Code ausbessern müssen. 


Gruß Joe


----------

