# Kommunikation mit externem Programm über TCP



## 1337iceskater (25. Mrz 2010)

Hallo Freunde der Java-Programmierung,

ich hab n Problem. Zur Situation: ich habe ein Projekt meines Vorgängers übernommen. Dabei muss ich eine Kommunikation zwischen einem externen Programm und einer Java-App herstellen. Er wollte das damals über TCP machen und hat auch shcon Klassen dafür geschrieben, die ich euch jetzt mal zeigen möchte:

ClientKlasse:

```
import java.io.*;

import java.net.*;

import java.lang.Thread;





/**

 * @author MiDaAI07

 *

 */

public class Client extends Thread

{

	private Socket  clientSocket = null;

	private PrintWriter out = null;	

	private BufferedReader in = null;

	private String serverIP = "";

	private int port = 4444;

	

	public static final String	MOVE_COMMAND		= "MOVE";

	public static final String	HOR_COMMAND			= "H";

	public static final String	VER_COMMAND			= "V";

	public static final String	COMMAND_SEPARATOR	= ",";

	public static final String	SELECT_COMMAND		= "SELECT";

	

	private String command ="";

	private int xPos;

	private int yPos;

	private String firstDir ="";

	private int deltaHor;

	private int deltaVer;

	

	

	/**

	 * This method parses the message and performs GameField.doMove method.

	 * @param message

	 */

	private void parseMessage(String message)

	{

		String[] splittedCommand = message.split(COMMAND_SEPARATOR);

		

		command = splittedCommand[0];

		

		if(command.startsWith(MOVE_COMMAND))

		{

			xPos = Integer.valueOf(splittedCommand[1]);

			yPos = Integer.valueOf(splittedCommand[2]);

			firstDir = splittedCommand[3];

			deltaHor = Integer.valueOf(splittedCommand[4]);

			deltaVer = Integer.valueOf(splittedCommand[5]);

			boolean startVertical = firstDir.startsWith(VER_COMMAND);

			int newX = xPos + deltaHor;

			int newY = yPos + deltaVer;

			

			//GameField.doMove(xPos,yPos,newX,newY,startVertical)

		}

		else if(command.startsWith(SELECT_COMMAND))

		{

			xPos = Integer.valueOf(splittedCommand[1]);

			yPos = Integer.valueOf(splittedCommand[2]);

			//GameField.setSelected(xPos,xPos);

		}

		

	}

	

	public boolean isLocal()

	{

		String ip = clientSocket.getInetAddress().toString();

		return ip.startsWith("/127.0.0.");

	}

	

	/**

	 * Send a Message to Server

	 * @param command

	 */

	public boolean send(String command)

	{

		for(int i=0;i<10;i++)

		{

		try {

			out.println(command);

			return true;

		} catch (RuntimeException e) 

		{

			try {

				Thread.sleep(500);

			} catch (InterruptedException e1) {

				// TODO Auto-generated catch block

			}

			e.printStackTrace();

		}

		}

		return false;

		

	}



	/**

	 * Connect to Server

	 */

	public void connect()

	{

		start();

	}

	

	/**

	 * Konstruktor, der den Client als Thread aufruft.

	 * Dieses Object repr�sentiert das Client-seitige Ende der Verbindung zwischen Client und Server.

	 */

	public Client(/*KomSchnittstelle kom,*/ String ip, int port) 

	{

		this.serverIP = ip;

		this.port = port;

	}



	/**

	 * 

	 */

	public void run()

	{

		

		try 

		{

			clientSocket = new Socket(serverIP,port);

			out = new PrintWriter(clientSocket.getOutputStream(),true);

			in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

					

			while(true && !isInterrupted() )

			{

				System.out.println(in.readLine());

			}

			



		} 

		catch (UnknownHostException e) {e.printStackTrace();} 

		catch (IOException e) {e.printStackTrace();}

		

		



	}

}
```

ServerKlasse:

```
import java.io.*;

import java.net.*;

import java.lang.Thread;



/**

 * 

 */



/**

 * @author MiDaAI07

 *

 */

public class Server extends Thread 

{

	private Socket clientSocket = null;

	private PrintWriter out = null;	

	private BufferedReader in = null;

	private int port = 4444;

	

	public static final String	MOVE_COMMAND		= "MOVE";

	public static final String	HOR_COMMAND			= "H";

	public static final String	VER_COMMAND			= "V";

	public static final String	COMMAND_SEPARATOR	= ",";

	public static final String	SELECT_COMMAND		= "SELECT";

	

	/**

	 * Send a Message to Client

	 * @param command

	 */

	public boolean send(String command)

	{

		for(int i=0;i<10;i++)

		{

		try {

			this.out.println(command);

			return true;

		} catch (RuntimeException e) 

		{

			try {

				Thread.sleep(500);

			} catch (InterruptedException e1) {

				// TODO Auto-generated catch block

			}

			e.printStackTrace();

		}

		}

		return false;

		

	}

	

	

	/**

	 * Start Server

	 */

	public void startServer()

	{

		start();

	}

	

	

	/**

	 * Konstruktor, der den Server als thread aufruft.

	 * Dieses Object repr�sentiert das Server-seitige Ende der Verbindung zwischen Client und Server.

	 */

	public Server(/*KomSchnittstelle kom,*/int port) 

	{

		this.port = port;

	}



	/**

	 * 

	 */

	public void run()

	{

		ServerSocket serverSocket = null;

		int serverSocketPort = port;

		
		

		try 

		{

			serverSocket = new ServerSocket(serverSocketPort);

			clientSocket = serverSocket.accept();

			this.out = new PrintWriter(clientSocket.getOutputStream(),true);

			in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

			

			while(true)

			{

				System.out.println(in.readLine());

			}



		}

		catch (IOException e) {

			// TODO Auto-generated catch block

			System.err.print("");

			e.printStackTrace();

		}


	}

}
```

Jetzt zu meinem Problem: Die Kommunikation läuft indem man entweder den Client in der Java-App und den Server in der externen App definiert oder umgedreht. Das soll dabei wohl keine Rolle spielen. Ist die externe App der Client, kommt bei dem Aufruf der Send-Methode im Server eine NullPointer-Exception, da angeblich der outputstream = null sei. Wenn die externe App Server ist, kommt beim Aufruf der Send-Methode im Client ein Output in Eclipse, der unendlich lange "null" ausgibt. Jedes "null" hat dabei eine eigene Zeile.

Leider kenne ich mich mit Netzwerkprogrammierung noch nicht so gut aus, daher hab ich leider auch keine Idee woran es liegen könnte. Wenn man allerdings sowohl Client als auch Server in einer Java-App definiert, läuft das ganze einwandfrei.

Ich hoffe ihr könnt mir helfen.

LG Stefan


----------



## Atze (25. Mrz 2010)

es kann sein (nehmen wir an, du startest den server und den client in einer main-methode einer testklasse), dass der server läuft, du den client mit connect() startest und dann send(...) aufrufst, ohne das der thread aber läuft, wodurch das objekt zwar existiert, aber dein "out" noch nicht initialisiert ist! nur weil der client start vor dem send(...) im der main steht heißt es nicht, dass der client thread läuft wenn du send(...) aufrufst, denn wann ein thread startet bestimmt das drunterliegende os! die main kann da schneller sein. entweder du wartest beim senden ein wenig, oder du überprüfst, ob der client wirklich schon läuft.

über diese connect() und startServer() methoden würde ich mir vielleicht auch nochmal gedanken machen, die rufen ja eh nur die start() auf, die ja eh schon public sind. es sein den, du willst vor dem starten noch irgendwas machen.


----------



## 1337iceskater (25. Mrz 2010)

Hallo und danke für die schnelle Antwort!

Jetzt aber ein weiteres Problem: das starten des Threads ist sicherlich schon ausgeführt, da ich die send-methode selber durch nen JButton aufrufe. Weiterhin ist die externe App keine Java-App. Könnte es sein, dass das Problem daran liegt? Ich dachte, dass TCP Programmiersprachen unabhängig wäre.

Ich hoffe das lüftet Fragen.

LG Stefan


----------

