performance - I'm having troubles with Java sockets in a client/server type application when having to accept many connections -
first of all, reading. first time in stackoverflow user, although i've read , found useful solutions :d. way, sorry if i'm not clear enough explaining myself, know english isn't good.
my socket based program having strange behaviour, , performance issues. client , server communicate each other reading/writing serialized objects object input , output streams, in multi-threaded way. let me show code basics. have simplified more readable , complete exception handling example intentionally ommited. server works this:
server:
// (...) public void serve() { if (serversocket == null) { try { serversocket = (sslserversocket) sslserversocketfactory .getdefault().createserversocket(port); serving = true; system.out.println("waiting clients..."); while (serving) { sslsocket clientsocket = (sslsocket) serversocket.accept(); system.out.println("client accepted."); //ljserverthread class below new ljserverthread(clientsocket).start(); } } catch (exception e) { // exception handling code (...) } } } public void stop() { serving = false; serversocket = null; } public boolean isserving() { return serving; } ljserverthread class, 1 instance created per client:
private sslsocket clientsocket; private string ip; private long starttime; public ljserverthread(sslsocket clientsocket) { this.clientsocket = clientsocket; starttime = system.currenttimemillis(); this.ip = clientsocket.getinetaddress().gethostaddress(); } public synchronized string getclientaddress() { return ip; } @override public void run() { objectinputstream in = null; objectoutputstream out = null; //this protocol handling object, , see below, //it works processing object received , returning response. ljprotocol protocol = new ljprotocol(); try { try { in = new objectinputstream(new bufferedinputstream( clientsocket.getinputstream())); out = new objectoutputstream(new bufferedoutputstream( clientsocket.getoutputstream())); out.flush(); } catch (exception ex) { // exception handling code (...) } ljpacket output; while (true) { output = protocol.processmessage((ljpacket) in.readobject()); // when object received finish mark, // protocol.processmessage()object returns null. if (output == null) { break; } out.writeobject(output); out.flush(); out.reset(); } system.out.println("client " + ip + " finished successfully."); } catch (exception ex) { // exception handling code (...) } { try { out.close(); in.close(); clientsocket.close(); } catch (exception ex) { // exception handling code (...) } { long stoptime = system.currenttimemillis(); long runtime = stoptime - starttime; system.out.println("run time: " + runtime); } } } and, client, this:
private sslsocket socket; @override public void run() { ljprotocol protocol = new ljprotocol(); try { socket = (sslsocket) sslsocketfactory.getdefault() .createsocket(inetaddress.getbyname("here-goes-hostip"), 4444); } catch (exception ex) { } objectoutputstream out = null; objectinputstream in = null; try { out = new objectoutputstream(new bufferedoutputstream( socket.getoutputstream())); out.flush(); in = new objectinputstream(new bufferedinputstream( socket.getinputstream())); ljpacket output; // client starts connection, sends first //object. out.writeobject(/* first object */); out.flush(); while (true) { output = protocol.processmessage((ljpacket) in.readobject()); out.writeobject(output); out.flush(); out.reset(); } } catch (eofexception ex) { // if goes ok, when server disconnects eof should happen. system.out.println("suceed!"); } catch (exception ex) { // (...) } { try { // first strange behaviour: // have comment "out.close()" line, else, exception // thrown always. out.close(); in.close(); socket.close(); } catch (exception ex) { system.out.println("this shouldn't happen!"); } } } } well, see, ljserverthread class handles accepted clients in server side, measures time takes... normally, takes between 75 - 120 ms (where x ip):
- client x finished successfully.
- run time: 82
- client x finished successfully.
- run time: 80
- client x finished successfully.
- run time: 112
- client x finished successfully.
- run time: 88
- client x finished successfully.
- run time: 90
- client x finished successfully.
- run time: 84
but suddenly, , no predictable pattern (at least me):
- client x finished successfully.
- run time: 15426
sometimes reaches 25 seconds! ocasionally small group of threads go little slower doesn't worry me much:
- client x finished successfully.
- run time: 239
- client x finished successfully.
- run time: 243
why happening? perhaps because server , client in same machine, same ip? (to tests execute server , client in same machine, connect on internet, public ip).
this how test this, make requests server in main():
(int = 0; < 400; i++) { try { new ljclientthread().start(); thread.sleep(100); } catch (exception ex) { // (...) } } if in loop without "thread.sleep(100)", connection reset exceptions (7 or 8 connections resetted out of 400, more or less), think understand why happens: when serversocket.accept() accepts connection, small amount of time has spent reach serversocket.accept() again. during time, server cannot accept connections. because of that? if not, why? rare 400 connections arriving server @ same time, happen. without "thread.sleep(100)", timing issues worse also.
thanks in advance!
updated:
how stupid, tested in localhost... , doesn't give problem! , without "thread.sleep(100)", doesn't matter, works fine! why! so, can see, theory why connection reset beeing thrown not correct. makes things more strange! hope me... again! :)
updated (2):
i have found sightly different behaviours in different operating systems. develop in linux, , behaviour explained happening in ubuntu 10.10. in windows 7, when pause 100ms between connections, fine, , threads lighting fast, no 1 takes more 150ms or (no slow connection issues!). not happening in linux. however, when remove "thread.sleep(100)", instead of of connections getting connection reset exception, of them fail , throw exception (in linux of them, 6 or out of 400 failing).
phew! i've find out not os, jvm enviroment has little impact also! not big deal, noteworthy. using openjdk in linux, , now, oracle jdk, see reduce sleep time between connections, starts failing earlier (with 50 ms openjdk works fine, no exceptions thrown, oracle's 1 quite lot 50ms sleep time, while 100ms works fine).
the server socket has queue holds incoming connection attempts. client encounter connection reset error if queue full. without thread.sleep(100) statement, of clients trying connect relatively simultaneously, results in of them encountering connection reset error.
Comments
Post a Comment