Hallo,
ich habe eine Client-Server-Anwendung. Zum Anmelden an den Server sendet der Client einen String und bekommt vom Server eine Antwort. Die Antwort des Servers besteht aus 5 Zeilen, die _immer_ mit einem Carriage-Return (sogar \r\n) abgeschlossen werden.
Starte ich eine Client-Anfrage zum Login, empfange ich auch die entsprechende Antwort. Erst mal kein Problem.
Wenn ich jetzt aber 100 Threads starte, die alle diese Anfrage senden, terminiert das Programm plötzlich nicht mehr immer (sogar nur ziemlich selten). Dann bleibt der Rechner in BufferedReader.readLine() hängen.
Eine google-Suche hat mich zu diesem (alten) Bug-Eintrag für Java 1.5 geführt: Bug ID: 5073414 BufferedReader.readLine() multi-threading issue with line-feed handling
Ich benutze Java 1.6 (U13) und dort war dieser Fix realisiert; trotzdem bin ich noch einen Schritt weitergegangen, habe die Klasse (BufferedReader) kopiert und die gesamte "readLine(boolean)" synchronized gemacht -- ohne Erfolg.
Habt ihr vielleicht eine Idee, was falsch sein könnte?
Ich poste hier mal den gesamten Quellcode meines Testprogramms (Clientseitig) -- sorry, ist etwas lang, aber schon so kurz wie möglich ).
Danke für die Hilfe,
Philipp
ich habe eine Client-Server-Anwendung. Zum Anmelden an den Server sendet der Client einen String und bekommt vom Server eine Antwort. Die Antwort des Servers besteht aus 5 Zeilen, die _immer_ mit einem Carriage-Return (sogar \r\n) abgeschlossen werden.
Starte ich eine Client-Anfrage zum Login, empfange ich auch die entsprechende Antwort. Erst mal kein Problem.
Wenn ich jetzt aber 100 Threads starte, die alle diese Anfrage senden, terminiert das Programm plötzlich nicht mehr immer (sogar nur ziemlich selten). Dann bleibt der Rechner in BufferedReader.readLine() hängen.
Eine google-Suche hat mich zu diesem (alten) Bug-Eintrag für Java 1.5 geführt: Bug ID: 5073414 BufferedReader.readLine() multi-threading issue with line-feed handling
Ich benutze Java 1.6 (U13) und dort war dieser Fix realisiert; trotzdem bin ich noch einen Schritt weitergegangen, habe die Klasse (BufferedReader) kopiert und die gesamte "readLine(boolean)" synchronized gemacht -- ohne Erfolg.
Habt ihr vielleicht eine Idee, was falsch sein könnte?
Ich poste hier mal den gesamten Quellcode meines Testprogramms (Clientseitig) -- sorry, ist etwas lang, aber schon so kurz wie möglich ).
Danke für die Hilfe,
Philipp
Code:
package com.tensegrity.apidemo;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import com.tensegrity.palojava.http.HttpParser;
class SimplePaloClient {
private static final String HOST = "127.0.0.1";
private static final String PORT = "7778";
private static final byte[] CRLF = new byte[] {(byte) 13, (byte) 10};
//some palo server commands:
private static final String LOGIN_REQUEST =
"GET /server/login?user=admin&password=21232f297a57a5a743894a0e4a801fc3 HTTP/1.1\r\n";
private Socket srvSocket;
private BufferedOutputStream toServer;
private BufferedInputStream fromServer;
public final synchronized void connect() {
try {
srvSocket = new Socket(HOST, Integer.parseInt(PORT));
toServer = new BufferedOutputStream(srvSocket.getOutputStream());
fromServer = new BufferedInputStream(srvSocket.getInputStream());
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public final synchronized void disconnect() {
if(srvSocket == null)
return;
try {
//close all streams...
toServer.close();
fromServer.close();
//and finally the socket:
srvSocket.close();
srvSocket = null;
} catch (IOException e) {
e.printStackTrace();
}
}
public final synchronized void login() {
//send login request:
try {
send(LOGIN_REQUEST);
} catch (ConnectException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private final synchronized String send(String request)
throws ConnectException, IOException {
System.out.println("REQUEST: "+request);
try {
toServer.write(request
.getBytes(HttpParser.DEFAULT_CHARACTER_ENCODING));
toServer.write(CRLF);
toServer.flush();
// read response:
String response = readLine();
return response;
} catch (SocketException se) {
se.printStackTrace();
} catch (InterruptedIOException ie) {
ie.printStackTrace();
}
return null;
}
private final synchronized String readLine() throws IOException {
int cl = -1;
String line;
StringBuilder buf = new StringBuilder();
BufferedReader reader =
new BufferedReader(new InputStreamReader(fromServer));
while((line=reader.readLine()) != null) {
System.out.println("RESPONSE LINE: "+line);
buf.append(line);
}
return buf.toString();
}
}
public class SimpleClientMultipleThreadTest {
public static final void main(String[] args) {
int threads = 100;
final int finished[] = {0};
final int errors[] = {0};
final ArrayList <SimplePaloClient> clients =
new ArrayList<SimplePaloClient>();
for(int i = 0; i < threads; ++i){
final String name = Integer.toString(i);
Thread thread = new Thread(new Runnable(){
public void run() {
try{
SimplePaloClient client = new SimplePaloClient();
client.connect();
client.login();
clients.add(client);
System.err.println("start thread: "+name);
}catch(Throwable e){
e.printStackTrace();
errors[0]++;
}
finished[0]++;
System.err.println("finished thread: "+name);
System.err.println("total finished: "+finished[0]);
}
},Integer.toString(i));
thread.start();
}
while(finished[0] != threads){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(SimplePaloClient client : clients)
client.disconnect();
}
}
Zuletzt bearbeitet: