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
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