FULL PRODUCT VERSION : java version "1.5.0_01" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08 Java HotSpot(TM) Client VM (build 1.5.0_01-b08, mixed mode, sharing) ADDITIONAL OS VERSION INFORMATION : Windows 2000 service pack 4 A DESCRIPTION OF THE PROBLEM : I need to use Http 1.1 persistent connection capabilities of the class java.net.HttpUrlConnection to run my http client. My http client sends multiple requests to a servlet running in Tomcat 5.0.19 web server and after 5 sec it doesn't send a message the underlying socket is replaced with another socket (I'm using TCPView to view the state of the tcp sockets). In particular I need to estabilish 'long-lived' tcp connection but in this way it's not possible because I can't handle the keepAliveTimeOut. By analyzing the source code of HttpUrlConnection and related classes, and Tomcat connector, I've discovered that: -in the sun client classes, in the cases of 'noProxy', the keepAliveTimeOut is hardcoded and is 5 sec: but if it receives something like: "timeout=40, max=5" in the "Keep-Alive" header property it should take it into account; besides, it seems to be no limit about the number of requests I can do on the underlying socket -in Tomcat, setting the property maxKeepAliveRequests="-1", the socket is never closed by the web server, and the connectionTimeout="20000" doesn't create problems; besides it seems to be hardcoded a keepAliveTimeOut of 60 sec. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Simply execute the test methods with and without the codeblock surrounded by th line comments: //-------------- .... //-------------- EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - Among client side and server side, the stronger keepAliveTimeOut constraint is the Tomcat constraint: connectionTimeout="20000"; after this there is the "timeout=40... of the client, and so the 60 sec hardcoded in Tomcat. So, running the method 'request(false)' including the codeblock surrounded by th line comments: //-------------- .... //-------------- the socket should remain the same if i don't send a message in 20 sec (connectionTimeout="20000" ) ACTUAL - the socket is replaced randomly; it is replaced much frequently if the frequency of the requests is higher; if I exclude the code inside the //-------------- .... //-------------- it is replaced after 5 sec if I send norequest REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- ==============CLIENT SIDE============== private synchronized void request(boolean close){ try{ con=(HttpURLConnection) url.openConnection(); con.setDoInput(true); con.setDoOutput(true); con.setUseCaches(false); con.setRequestProperty("Content-Type", "application/octet-stream"); //------------ if(close) con.setRequestProperty("connection","close"); else{ con.setRequestProperty("connection","keep-alive"); con.setRequestProperty("Keep-Alive", "timeout=40, max=5"); } //--------- ObjectOutputStream os=new ObjectOutputStream(con.getOutputStream()); os.writeObject("xx"); os.close(); ObjectInputStream is = new ObjectInputStream(con.getInputStream()); Object o = is.readObject(); is.close(); } catch (Exception e) { e.printStackTrace(); } } =================================== ==============SERVER SIDE========== servlet with: protected void service(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { String connHeader=httpServletRequest.getHeader("connection"); if(connHeader!=null && connHeader.toLowerCase().equals("keep-alive")){ String kaHeader=httpServletRequest.getHeader("Keep-Alive"); if(kaHeader!=null){ httpServletResponse.setHeader("Connection",connHeader); httpServletResponse.setHeader("Keep-Alive",kaHeader); } } ObjectInputStream is = new ObjectInputStream(httpServletRequest.getInputStream()); Object o=null; try {o=is.readObject();}catch (Exception e) {e.printStackTrace();} is.close(); ObjectOutputStream os = new ObjectOutputStream(httpServletResponse.getOutputStream()); os.writeObject("tnx"); os.close(); } =================================== ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : I tried this workaround: -set the response header property ("Keep-Alive","timeout=40, max=5") in my server-side code, so to let the client side (class sun.net.www.http.HttpClient) read it; -set maxKeepAliveRequests="-1" in Tomcat; the things seem to work much better, but sometimes, unexpectedly, the tcp socket is replaced, also after 1-2 sec from the last mesage. Besides, after some minutes the client cpu raise to 90% ###@###.### 2005-03-09 09:36:42 GMT
|