# Selbe Streams mehrfach nutzen (zusätl. Thread)



## Kyran (8. Jul 2007)

Hallo Leute, folgendes Problem:

Ich hab in meiner Klasse  jeweils einen ObjectInput/Outputstream, mit dem ich Daten senden / empfangen kann. Läuft soweit auch. Jetzt möchte ich aber zusätzlich nen Thread starten, dem ich diese Streams übergebe, der soll einfach nur Lauschen und wenn entsprechendes empfangen wurde reagieren.

Ist es möglich, die selben Streams also sogesehen doppelt zu verwenden?

kurzes beispiel:


```
Klasse:

                private ObjectInputStream ois;
                private ObjectOutputStream oos; 

                [...]

                Konstruktor der Klasse:

                oos = new ObjectOutputStream(socket.getOutputStream());
                ois = new ObjectInputStream(socket.getInputStream());

                [...]
                    Methoden die etwas senden ... und wenn nötig empfangen.
                    Gesendet wird, wenn die GUI in dieser Klasse eine Methode zum senden aufruft.
                [...]


                Threadstart:

                listen = new ListeningThread(Klasse.this,ois,oos);
                listen.start();


    Thread:                

        public ListeningThread(Klasse klasse, ObjectInputStream ois, ObjectOutputStream oos) {

		this.klasse = klasse;
		this.ois = ois;
        this.oos = oos;
        }

        [...]
            
        run(){

            [...]
        
                input = ois.readObject();        //hier wird der Fehler geworfen!        

            [...]
                
                Methoden die, wenn nötig, etwas machen.

            [...]
        }
```



Ich fange natürlich die Exception bei  input = ois.readObject() ab und bekomme folgende Fehlermeldung:

"invalid type code: 00"

Achja, readObject() blockiert auch nicht (klar, wird ja auch ne Exception geworfen ...) sondern wird zich mal durchlaufen und der fehler wird immer wieder angezeigt.



Ich hoffe ihr könnt mir weiterhelfen, ich bin echt am verzweifeln. Falls ich Fragen aufgeworfen hab, sagt bitte bescheid. (Entschuldigt die schlechte einrückung, die 
	
	
	
	





```
funktioniert stellt die nicht so dar wie ichs gern hätte ...)
```


----------



## SlaterB (9. Jul 2007)

der Fehler passiert wirklich nur, wenn das ganze in einem Thread abläuft?
hast du das genauer untersucht?

oder tritt er allgemein auf und das ganze hat nix mit Threads zu tun?



in jedem Falle solltest du ein vollständig lauffähiges Programm posten

alles was du auskommiert hast kann eh entfernt oder durch ein simples System.out.println ersetzt werden


----------



## Kyran (9. Jul 2007)

Also Senden und Empfangen findet auch in der "Klasse" statt, da funktioniert das ohne probleme (die "Klasse" ist der Client), natürlich gibs da noch den Server wo ebenfalls n Thread läuft, der lauscht dann auf "Befehle" vom Client. Funktioniert alles wunderbar. Ich muss halt nur den Client irgendwie auch zum lauschen bringen.


Den ganzen Code posten wird problematisch, weil das ein gewaltiges Projekt ist, an dem ich seit knapp drei einhalb monaten arbeite und das täglich mehrere Stunden. Sind also wohl über 10.000 zeilen code.

Müsst ich das vereinfacht neu schreiben ... problem ist, das mir dafür die Zeit fehlt, weil die Abgabe kurz bevor steht.

Ich hab das ganze jetzt mal so getestet, das ich den Client in eine lauschende schleife innerhalb der "Klasse" schiebe. Dadurch wird natürlich das gesamte Programm geblockt, bis etwas erhalten wurde, aber zum testen gehts ja ...

Innerhalb dieser lauschenden Schleife erhält der Client ohne probleme die Daten und ruft weitere methoden auf. Also daran liegts garantiert nicht.


Mein Auge liegt halt immer noch an der Tatsache, das ich eine Instanz(?) vom ObjectInputStream und eine Instanz(?) vom ObjektOutputStream an den Thread übergebe und da ebenfalls verwende und deswegen dieser Fehler erscheint.


----------



## tuxedo (9. Jul 2007)

Wieso lässt du den Stream nicht einfach in einen Thread laufen der

a) Die Auswertung macht und ggf. weitere schritte einleitet
b) die Daten weiter reicht

Also quasi das einmalig gelesene doppelt verwenden. So musst du nur einmal aus dem Stream lesen.


----------



## Kyran (9. Jul 2007)

Und zwar, weil ich gestern noch dachte, das dieser Thread blockiert wird bei readObject() ... ich also lokal keine methoden aus dem Thread aufrufen kann. (Also die "Klasse" keine Methode aus dem "Thread" aufrufen kann, solang der in dieser readObject Zeile ist). Heute morgen ist mir eingefallen, das das aber dennoch geht und ich das aufm Server auch schonmal gemacht habe!

Die Zeit rennt mir davon, aber wenn ichs heut noch schaffe das umzustellen, sag ich bescheid obs funktioniert hat.



> a) Die Auswertung macht und ggf. weitere schritte einleitet
> b) die Daten weiter reicht



Das Problem gestern war ja, das ich dachte, das der Thread blockiert wird und ich keine methoden von aussen in dieser Thread aufrufen kann, aber anscheinend gehts ja doch ... (hoff ich)


Wie gesagt, ich sag bescheid, aber rechnet eher heut abend nach 24 Uhr mit ner Antwort ^^


----------



## tuxedo (9. Jul 2007)

Eilt ja nicht... nur keine Hektik...


----------



## Kyran (9. Jul 2007)

Es klappt doch nicht ... ich hab auf jedenfall nur einen Thread und nur ein ObjectnputStream und ObjectOutputStream und dennoch bekomm ich den 

invalid type code: 00

fehler, mit dem ich nichts anfangen kann ...


Also der Thread, Konstruktor und run():


```
public ListeningThread(String host, int port, GameManagerFront game) {

		this.game = game;
		try {
			// Socket-Objekt fuer die Kommunikation mit Host/Port erstellen
			socket = new Socket(host, port);

			oos = new ObjectOutputStream(socket.getOutputStream());
			ois = new ObjectInputStream(socket.getInputStream());

		
		} catch (IOException e) {
			System.err.println("Fehler beim Socket-Stream öffnen: " + e);
			// Wenn im "try"-Block Fehler auftreten, dann Socket schließen:
			if (socket != null)
				try {
					socket.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			System.err.println("Socket geschlossen");
			System.exit(0);
		}
		
		// Verbindung erfolgreich hergestellt: IP-Adresse und Port ausgeben
		System.out.println("Verbunden: " + socket.getInetAddress() + ":"
				+ socket.getPort());
		
		try {
			oos.writeObject("Client verbunden");
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		// Begrüßungsmeldung vom Server lesen
		String message = null;
		try {
			System.out.println("-----------Client erwartet Begrüßung vom Server");
			message = (String) ois.readObject();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(message);
	}

            public void run(){
		
		String input = null;
		while(true){
			
			try {
				System.out.println("ListeningThread wartet und lauscht");
				input = (String) ois.readObject();
			} catch (Exception e) {
				System.out.println("--->Fehler beim Lesen vom Client (Aktion): ");
				System.out.println(e.getMessage());
			}

            [...]
    }
```

    Die Exception wird aufgerufen, sobald input = (String) ois.readObject(); betreten wird.

    Und hier das Gegenstück, der Server:


```
public MiniRiskServer(int port) throws IOException {
		
			// Server-Socket anlegen
			serverSocket = new ServerSocket(port);
			
			// Serverdaten ausgeben
			InetAddress ia = InetAddress.getLocalHost();
			System.out.println("Host: " + ia.getHostName());
			System.out.println("Server *" + ia.getHostAddress()	+ "* lauscht auf Port " + port);
		} catch (IOException e) {
			fail(e, "Eine Ausnahme trat beim Anlegen des Server-Sockets auf");
		}
		//acceptClientConnectRequests();
	}

	/**
	 * Methode zur Entgegennahme von Verbindungswünschen durch Clients.
	 * Die Methode fragt wiederholt ab, ob Verbindungsanfragen vorliegen
	 * und erzeugt dann jeweils ein PlayerClientRequestProcessor-Objekt mit dem 
	 * fuer diese Verbindung erzeugten Client-Socket.
	 */
	public void acceptClientConnectRequests() {
		game = new GameManager(); 
		try {
			while (true) { 
				Socket clientSocket = serverSocket.accept();
				int connectionNumber = game.getNumberOfThreads();
				PlayerClientRequestProcessor pcrp = new PlayerClientRequestProcessor(clientSocket, game, connectionNumber);
				game.addPCRP(pcrp);
				pcrp.start();
			}
		} catch (IOException e) {
			fail(e, "Fehler während des Lauschens auf Verbindungen");
		}
	}
```

PCRP ist der Thread der auf dem Server ausgeführt wird, der läuft wunderbar und ist genauso aufgebaut wie der Thread den ich euch oben gepostet hab.


----------

