Socket BufferedReader interrupten?

Volvagia

Top Contributor
Ist es irgendwie möglich, einen BufferedReader, der von einem SocketInputStream ließt, und auf einen Input wartet zu interrupten? Ich habe einen Thread, der die allgemeinen Daten von einen Programmzustand empfängt und behandelt. Jetzt soll aber ein komplett neuer Zustand geladen werden. Da wäre es wesendlich besser, den Thread zu pausieren oder stoppen, wärend dem Laden der Reihe nach die Befehle am Server zu senden, zu empfangen und den Thread danach neu zu starten, sonst gäbe es einfach nur ein Durcheinander.

Kennt da zufällig jemand eine Möglichkeit? :)
 

Volvagia

Top Contributor
Danke, aber ich glaube, ich habe es nicht richtig verstanden. (What about threads blocked on IO?)
Interrupt löst bei mir keine InterruptedIOException aus. Nebenbei kam ich noch auf die Idee einfach zu schließen, das blockiert leider auch wärend dem read().

Java:
public synchronized static Command read(Socket socket)
{		
	BufferedReader bufferedReader = getReader(socket);
	Command command = null;
	
	try
	{
		int incoming = 0;
		StringBuilder builder = new StringBuilder();
		
		//TODO Build in buffer.
		while((incoming = bufferedReader.read()) != -1 && incoming != '$')
			builder.append((char)incoming);
		command = new Command(builder.toString());
	}
	catch (SocketException e) {}
	catch (InterruptedIOException e)
	{
		System.out.println("Interrupted. :D");
	}
	catch (IOException e)
	{
		e.printStackTrace();
	}
	return(command);
}
/////////////////////////////////////
public void terminate()
{
	thread.interrupt();

	while(thread.isInterrupted()) {}
	
	try
	{
		thread.join();
	}
	catch (InterruptedException e)
	{
		e.printStackTrace();
	}
}

(Die Schleife in terminate() ist dazu da, darauf zu warten, das der Thread nicht mehr Interrupted ist, damit er nicht einfach durch das join durchrennt. interrupted() ist ja leider nicht so schön, weil es ja statisch ist.)
 

Marco13

Top Contributor
Hm. Dass die InterruptedIOException nicht unbedingt geworfen wird, steht ja in dem Artikel, und auch, wie man das Problem löst. Es wird der zugrundeligende InputStream geschlossen. Vielleicht kannst du das anwenden. In deinem Fall müßte entsprechend die interrupt-Methode des Threads, der readCommand ausführt, überschrieben und darin der BufferedReader geschlossen werden.
 

Empire Phoenix

Top Contributor
Wie wäre es damit, du setzt ein flag solange der nicht readen soll und wenn das gesetzt ist verwirft er einfach alles was er per read liest? Muss man natürlich die schleife etwas ausdehnen.
 

Marco13

Top Contributor
Ich denke, das Hauptproblem bezog sich darauf, dass man eben irgendwo irgendwann
something.read();
aufruft. Und der Thread bleibt in diesem read hängen. Und da kann man anscheinend nichts dagegen machen, außer "something" zu schließen *knirsch* ...
 

Volvagia

Top Contributor
Stimmt.
Danke, das habe ich überlesen. :oops:
Ich habe dafür dem Server jetzt umgebaut, dass alle Connection-Threads in eine HashMap mit der InetAdress.toString() verknüpft gespeichert werden. Wird die Verbindung getrennt, wird eine boolean auf true gesetzt, 30 Sekunden gewartet und dann die run() verlassen. Kommt aber stattdessen eine neue Verbindung mit der selben InetAdress ein, wird der Socket ersetzt und der sleep interrupted, wodurch er wieder zum Lesen anfängt. Das Problem dabei ist, das innerhalb des Zeitraums des disconnect einen Client gehijackt werden könnte. Wenn jemand den normalen Ablauf folgt, ist es kein Problem, da die alten Daten einfach neu von der DB gelesen werden. Wenn er aber in den 30 Sekunden mit einen externen Programm verbindet, und so den alten Thread fortführt könnte er eigendlich machen, was er will. :shock:

Hoffe, es ist trotzdem noch sicher genug. :reflect:
 

Empire Phoenix

Top Contributor
Naja wennde auf Clientsite zufälligen Port nimmst verringerste die ratechance erheblich, dann muss man eigentlich schon die Packete sniffen um das in 30 secs zuverläassig rauszufinden.
 

Volvagia

Top Contributor
Gute Idee. Wobei ich statt dem Port eine Session generieren werde, mit dem der Client später seinen Thread wieder mit dem neuen Socket ausstatten kann. Gegen Sniffer kann man eigendlich eh nichts tun, sobald der Spieler sich einloggt hat er den Passwort-Hash. Asymetrische Verschlüsselung erfordert warscheinlich zu viel Leistung.
 

Empire Phoenix

Top Contributor
Server schickt random string zu client, der md5 das mittem apssword zusammen, und schickt das zusammen mit username zurück,
server guckt password inner datenbank für usernamen nach, generiertselber hash zusammen mit dem vorherigen randomstring, und vergleicht.
 

Volvagia

Top Contributor
Dann müsste ich aber das Passwort im Klartext am Server speichern, und ich schätze, der Server stellt ein wesendlich attraktiveres Ziel als das Netzwerk dar.

Ich habe es jetzt so gemacht, dass der Client am Server auf Wunsch einen neuen Thread starten lassen oder einen alten Thread (sofern er den Key kennt und der Socket, dem der Thread benutzt getrennt wurde) übernehmen kann:

Java:
final Socket socket = serverSocket.accept();

new Thread("Handle new connection") {
	public void run()
	{
		Command cmd = Command.read(socket);
		
		synchronized (HANDLE_LOGIN_LOCK)
		{
			if(cmd.hasCommand(Command.COMMAND_LOGIN_NEW_CONNECTION_KEY))
			{
				String conKey = findConKey();
				Client client = new Client(socket, CLIENT_LIST, conKey);
				client.setName("Client: " + conKey);
				client.start();
				
				synchronized (CLIENT_LIST_LOCK)
				{
					CLIENT_LIST.put(conKey, client);
				}
				cmd = new Command(Command.COMMAND_LOGIN_THE_NEW_CONNECTION_KEY,
						Command.LOCATION_ANSWER);
				cmd.addParameter(conKey);
				cmd.send(socket);
			}
			else if(cmd.hasCommand(Command.COMMAND_LOGIN_USE_CONNECTION_KEY))
			{
				String conKey = cmd.getParameter(0);
				
				synchronized (CLIENT_LIST_LOCK)
				{
					Client client = CLIENT_LIST.get(conKey);
					if(client != null && client.isConnectionLost())
						client.reactivate(socket);
				}
			}
		}
	}
}.start();

private String findConKey()
{
	String conKey = null;
	synchronized (CLIENT_LIST_LOCK)
	{			
		do
		{
			StringBuilder builder = new StringBuilder();	
			
			for(byte b = 0; b < 32; b++)
			{
				int randNum = (int)(Math.random() * 16);
				builder.append(Integer.toHexString(randNum));
			}
			conKey = builder.toString();
		}
		while(CLIENT_LIST.get(conKey) != null);
	}
	return(conKey);
}

Ich denke, das bietet genug Sicherheit. :)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
M HTTP URLConnection + BufferedReader killt meine Umlaute Netzwerkprogrammierung 4
x46 byte[] über BufferedReader auslesen Netzwerkprogrammierung 18
X Socket [Anfänger] BufferedReader.readLine() lässt sich Zeit Netzwerkprogrammierung 1
B Socket BufferedReader.readLine() beenden ohne den Stream zu closen Netzwerkprogrammierung 7
C Socket BufferedReader.read(char[] buffer) blockiert unregelmäßig Netzwerkprogrammierung 3
J BufferedReader.ready() wird nicht true Netzwerkprogrammierung 10
A Socket BufferedReader.readLine() blockiert bis ein im Socket OutputStream was gesendet wird ... Netzwerkprogrammierung 9
B Multi-Threaded block bei BufferedReader.readLine() Netzwerkprogrammierung 8
S BufferedReader blockiert zu lange Netzwerkprogrammierung 4
P eine BufferedReader für alles ankommende Netzwerkprogrammierung 2
C 2 BufferedReader als Listener pro Socket (NICHT) möglich? Netzwerkprogrammierung 2
E BufferedReader.ready() immer false Netzwerkprogrammierung 8
R Mittels BufferedReader Objekte lesen? Netzwerkprogrammierung 5
AlClemento Sockets -> BufferedReader Problem Netzwerkprogrammierung 2
C Kollision von ObjectInputStream und BufferedReader ? Netzwerkprogrammierung 6
O BufferedReader.readline kommt nicht zurück Netzwerkprogrammierung 7
F BufferedReader Socket Netzwerkprogrammierung 2
B BufferedReader.readLine() ließt nicht vollständig ! ? Netzwerkprogrammierung 5
J Vom BufferedReader lesen -> hängt ohne Fehler,ohne Except Netzwerkprogrammierung 2

Ähnliche Java Themen


Oben