TCP Chat

dodlhuat

Mitglied
Hallo,

ich habe einen TCP Chat geschrieben, oder es zumindest versucht, denn jetzt hänge ich bei einem Fehler und komme nicht weiter.
Server und Client funktionieren so weit ganz gut, aber wenn mehrere Clients am Server angemeldet sind sollte eine geschriebene Nachricht an alle Clients gehen. Das passiert aber leider nur fast.
Denn wenn ich eine Nachricht an alle schicke, wird diese erst angezeigt sobald der Empfängerclient etwas eingibt. Wo der Fehler liegt weiß ich leider nicht.
Hier mal der Code des Serverthreads:
Code:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

public class TextServerHandler implements Runnable
{
	private Socket clientSocket;
	private String input = "";
	private String minusLeer = "";
	private int counter = 0;
	private boolean loggedIn = false;
	private boolean correct = false;
	private String password = "";
	private String user = "";
	private static Vector<NewUser> loggedInUsers = new Vector<NewUser>();
	private PrintWriter out = null;
	private BufferedReader in = null;
	
	public TextServerHandler(Socket _clientSocket) {
		this.clientSocket = _clientSocket;
	}
	
	@Override
	public void run() {
		try {
	      System.out.println("Thread " + Thread.currentThread().getId() + " für Clientanfrage gestartet !");

	      out = new PrintWriter(this.clientSocket.getOutputStream(), true);
	      in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
	      
	      String strInput = null;
	      System.out.println ("Thread " + Thread.currentThread().getId() + " für Clientanfrage wartet auf Antwort...");
	      
	      //warten bis keine eingabe mehr kommt
	      while ((strInput = in.readLine()) != null) {
	        System.out.println("Thread " + Thread.currentThread().getId() + ": Eingabe: " + strInput);
	
	        //Login überprüfen
	        if(strInput.startsWith("!login") && loggedIn == false) {
	        	for(int i = 7; i < strInput.length(); i++) {
	        		input += strInput.charAt(i);
	        		//leerzeichen erkennen -> da fängt das nächste wort an
	        		if(strInput.charAt(i) == ' ') {
	        			counter++;
	        			//wenn der counter 1 ist, ists der username -> erstes wort nach !login
	        			if(counter == 1) {
	        				user = minusLeer;
	        				input = "";
	        			}
	        			//wenn der counter 2 ist, ists das passwort
	        			else if(counter == 2) {
	        				password = input;
	        				input = "";
	        			}
	        			//zu viel wörter, also fehler
	        			else {
	        				input = "";
	        				user = "";
	        				password = "";
	        				correct = false;
	        			}
	        		}
	        		//am ende angelangt
	        		else if(i == strInput.length()-1) {
	        			//wenn counter größer 1, zu viele wörter, also fehler
	        			if(counter > 1) {
	        				input = "";
	        				user = "";
	        				password = "";
	        				correct = false;
	        			}
	        			//passwort setzen
	        			else {
	        				password = input;
	        				input = "";
	        			}
	        		}
	        		minusLeer = input;
	        	}
	        	//wenn benutzer und passwort eingegeben worden sind
	        	if(!user.equals("") && !password.equals("")) {
	        		int found = 99;
	        		//user aus der users.properties durchgehen
	        		for(int i = 0; i < TextServer.user.size(); i++) {
	        			//wenn der benutzername gefunden wird, die stelle speichern
	        			if(user.equals(TextServer.user.elementAt(i))) {
	        				found = i;
	        			}
	        		}
	        		if(found != 99) {
	        			//das passwort zum usernamen vergleichen und wenn korrekt einloggen	
	        			if(TextServer.pass.elementAt(found).equals(password)) {
		        			correct = true;
		        			loggedIn = true;
		        			setLoginTime();
		        		}
	        		}
	        		else {
	        			correct = false;
	        		}
	        	}
	        	if(correct == false) {
	        		out.println("Wrong username or password");
	        	}
	        	else if (correct == true) {
	        		out.println("Successfully logged in");
	        	}
	        }
	        //wenn man schon eingeloggt ist gehen andere commandos
	        else if(loggedIn == true) {
	        	if(strInput.startsWith("!logout")) {
		        	loggedIn = false;
		        	correct = false;
		        	counter = 0;
		        	out.println("Successfully logged out");
		        }
		        else if(strInput.startsWith("!send")) { 
		        	String message = "";
		        	for(int i = 6; i < strInput.length(); i++) {
		        		message += strInput.charAt(i);
		        	}
		        	sendToAll(message);
		        }
		        else if(strInput.startsWith("!msg")) {
		        	sendLine(strInput);
		        }
		        else if(strInput.startsWith("!list")) {
		        	out.println("list");
		        }
		        else if(strInput.startsWith("!info")) {
		        	out.println("info");
		        }
		        else {
		        	out.println("invalid command");
		        }
	        }
	        else {
	        	out.println("no valid command / not logged in");
	        }

	        System.out.println("Thread " + Thread.currentThread().getId() + " für Clientanfrage next round");
	      }
	
	      System.out.println("Thread " + Thread.currentThread().getId() + " ist fertig!");
	    }
	    catch (IOException ioEx)
	    {
	      System.out.println("Fehler beim Schreiben:" + ioEx.getMessage());
	    }
	  }

	//einloggzeit erstellen und neuen user in der liste anlegen
	private void setLoginTime() {
		Date now = new Date(System.currentTimeMillis()); 
		DateFormat day = new SimpleDateFormat("dd.MM.yyyy");
		DateFormat time = new SimpleDateFormat("HH:mm");
		String day_s = day.format(now);
		String time_s = time.format(now);
		NewUser loginUser = new NewUser(day_s, time_s, this.clientSocket.getInetAddress(), user, this.clientSocket);
		synchronized(loggedInUsers) { loggedInUsers.add(loginUser); }
	}
	
	public void sendLine(String text) {
		out.println(text);
	}
	
	private void sendToAll(String text) throws IOException {
		synchronized(loggedInUsers) {
			for(int i = 0; i < loggedInUsers.size(); i++) {
				PrintWriter out_to_all = new PrintWriter(loggedInUsers.elementAt(i).getSocket().getOutputStream(), true);
				out_to_all.println(text);
				out_to_all.flush();
			}
		}
	}
}

und der Code für den Client:

Code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;


public class TextClient
{
  
  public static void main(String[] args)
  {
    System.out.println ("Text eingeben, 'Enter' schickt ihn zum Server. Eingabe von '!exit' zum Beenden!");
    
    // Tastatureingaben werden eingelesen:
    BufferedReader reader = new BufferedReader ( new InputStreamReader (System.in));
    
    //Server-Verbindung aufbauen:
    Socket socketServer = null;
    try
    {
      socketServer = new Socket ("localhost", 13000);
    }
    catch (UnknownHostException ex)
    {
      System.out.println("UnknownHostException bei Verbindung zu Host 'localhost', Port 13000: " + ex.getMessage());
      System.exit(-1);
    }
    catch (IOException ex)
    {
      System.out.println("IOException bei Verbindung zu Host 'localhost', Port 13000: " + ex.getMessage());
      System.exit(-1);
    }
    
    try
    {
      //Eingabe-Reader/Ausgabe-Writer erzeugen:
      PrintWriter out = new PrintWriter(socketServer.getOutputStream(), true);
      BufferedReader in = new BufferedReader(new InputStreamReader(socketServer.getInputStream()));
      //Solange der User etwas eingibt (und danach Enter drückt), werden die Daten
      //zum Server geschickt. Eingabe von "!exit" beendet alles.
      String textInput = null;
      while ((textInput = reader.readLine()) != null && !"!exit".equals(textInput))
      {
    	  if(textInput.startsWith("!send")) {
    		  
    	  }
    	  //Ab zum Server:
    	  out.println(textInput);
    	  out.flush();

    	  System.out.println("Warten auf Server-Antwort...");
    	  //Server schickt uns "toUpper" der Eingabe:
    	  String textServer = in.readLine();
    	  System.out.println("Server-Antwort: " + textServer);
      }
      //User hat "!exit" eingegeben: Socket dichtmachen.
      socketServer.close();
    }
    catch (IOException e)
    {
      System.out.println ("IOException: " + e.getMessage());
      System.exit(-1);
    }
  }
}

Bin für jede Hilfe dankbar!
 
Tja, so wars. So einfach und ich hab's nicht gesehen. Habe immer erst nach einer Eingabe neu vom Server gelesen. Jetzt mach ich das mittels Thread die ganze Zeit, und es funktioniert.
Also Danke für den Tip
 

Neue Beiträge

Zurück