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? 🙂
 
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.)
 
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.
 
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.
 
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* ...
 
Stimmt.
Danke, das habe ich überlesen. 😳
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:
 
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.
 
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.
 
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.
 
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. 🙂
 

Neue Themen


Zurück
Oben