From: Niels Campbell (
niels_campbell_at_lycos.co.uk)
Date: 01/23/04
Date: 23 Jan 2004 09:14:16 -0800
After spending nearly 3 days on this problem to come up with a
solution I think it is only right to post the solution.
I found that you can't set the soTimeout on an HttpURLConnection
as
the sockets are encapsulated within the HttpURLConnection
implementation.
I found Mike Reiche solution in which he uses a handler to set a
timeout value. This nearly worked. Looking at the code in the rt.jar I
found that the initial timeout was working, but the call
parseHTTP(...) in HttpClient was then attempting a second connection
which had a time out value of 0(infinite).
I modified the code to override the doConnect() in the
NetworkClient
and managed to get a timeout occurring. To be exact two timeouts
occur.
It works on
java version "1.4.0_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_03-b04)
Java HotSpot(TM) Client VM (build 1.4.0_03-b04, mixed mode)
and
java version "1.2.2"
Classic VM (build JDK-1.2.2_013, native threads, symcjit)
Anyway here is the code, excuse the formatting.
/* HttpTimeoutURLConnection.java */
import java.net.*;
import java.io.*;
import sun.net.www.http.HttpClient;
// Need to override any function in HttpURLConnection that create
a
new HttpClient
// and create a HttpTimeoutClient instead. Those functions are
// connect(), getNewClient(), getProxiedClient()
public class HttpTimeoutURLConnection extends
sun.net.www.protocol.http.HttpURLConnection
{
public HttpTimeoutURLConnection(URL u, HttpTimeoutHandler
handler,
int iSoTimeout)
throws IOException
{
super(u, handler);
HttpTimeoutClient.setSoTimeout(iSoTimeout);
}
public void connect() throws IOException
{
if (connected)
{
return;
}
try
{
if ("http".equals(url.getProtocol())) // &&
!failedOnce <-
PRIVATE
{
// for safety's sake, as reported by KLGroup
synchronized (url)
{
http = HttpTimeoutClient.getNew(url);
}
}
else
{
if (handler instanceof HttpTimeoutHandler)
{
http = new HttpTimeoutClient(super.url,
((HttpTimeoutHandler)handler).getProxy(),
((HttpTimeoutHandler)handler).getProxyPort());
}
else
{
throw new IOException("HttpTimeoutHandler
expected");
}
}
ps = (PrintStream)http.getOutputStream();
}
catch (IOException e)
{
throw e;
}
connected = true;
}
protected HttpClient getNewClient(URL url)
throws IOException
{
HttpTimeoutClient httpTimeoutClient = new HttpTimeoutClient
(url, (String)null, -1);
return httpTimeoutClient;
}
protected HttpClient getProxiedClient(URL url, String
s, int i)
throws IOException
{
HttpTimeoutClient httpTimeoutClient = new HttpTimeoutClient
(url, s, i);
return httpTimeoutClient;
}
}
/* HttpTimeoutHandler.java */
import java.net.*;
import java.io.IOException;
public class HttpTimeoutHandler extends
sun.net.www.protocol.http.Handler
{
private int iSoTimeout=0;
public HttpTimeoutHandler(int iSoTimeout)
{
// Divide the time out by two because two connection attempts
are made
// in HttpClient.parseHTTP()
if (iSoTimeout%2!=0)
{
iSoTimeout++;
}
this.iSoTimeout = (iSoTimeout/2);
}
protected java.net.URLConnection openConnection(URL u) throws
IOException
{
return new HttpTimeoutURLConnection(u, this, iSoTimeout);
}
protected String getProxy()
{
return proxy;
}
protected int getProxyPort()
{
return proxyPort;
}
}
/* HttpTimeoutFactory.java */
import java.net.*;
public class HttpTimeoutFactory implements
URLStreamHandlerFactory
{
private int iSoTimeout=0;
public HttpTimeoutFactory(int iSoTimeout)
{
this.iSoTimeout = iSoTimeout;
}
public URLStreamHandler createURLStreamHandler(String str)
{
return new HttpTimeoutHandler(iSoTimeout);
}
}
/* HttpTimeoutClient.java */
import sun.net.www.http.HttpClient;
import java.net.*;
import sun.net.*;
import sun.net.www.*;
import java.io.*;
public class HttpTimeoutClient extends HttpClient
{
private static int iSoTimeout=0;
public HttpTimeoutClient(URL url, String proxy, int
proxyPort)
throws IOException
{
super(url, proxy, proxyPort);
}
public HttpTimeoutClient(URL url) throws IOException
{
super(url, null, -1);
}
public static HttpTimeoutClient getNew(URL url)
throws IOException
{
HttpTimeoutClient httpTimeoutClient = (HttpTimeoutClient)
kac.get(url);
if (httpTimeoutClient == null)
{
httpTimeoutClient = new HttpTimeoutClient (url); // CTOR
called openServer()
}
else
{
httpTimeoutClient.url = url;
}
return httpTimeoutClient;
}
public static void setSoTimeout(int iNewSoTimeout)
{
iSoTimeout=iNewSoTimeout;
}
public static int getSoTimeout()
{
return iSoTimeout;
}
// Override doConnect in NetworkClient
protected Socket doConnect(String s, int i)
throws IOException, UnknownHostException, SocketException
{
Socket socket=super.doConnect(s,i);
// This is the important bit
socket.setSoTimeout(iSoTimeout);
return socket;
}
}
/* Example use */
import java.util.*;
import java.io.*;
import java.net.*;
public class SystemProperty
{
public static void main(String[] args)
{
String sSoapUrl="http://192.168.0.223/mobaqSecurity/SslTunnelServlet";
System.out.println("Connecting to [" + sSoapUrl + "]");
URLConnection urlConnection = null;
URL url=null;
try
{
url = new URL((URL)null, sSoapUrl, new
HttpTimeoutHandler(10000));
urlConnection = url.openConnection();
// Optional
url.setURLStreamHandlerFactory(new
HttpTimeoutFactory(10000));
System.out.println("Url class
["+urlConnection.getClass().getName()+"]");
}
catch (MalformedURLException mue)
{
System.out.println(">>MalformedURLException<<");
mue.printStackTrace();
}
catch (IOException ioe)
{
System.out.println(">>IOException<<");
ioe.printStackTrace();
}
HttpURLConnection httpConnection =
(HttpURLConnection)urlConnection;
System.out.println("Connected to [" + sSoapUrl + "]");
byte[] messageBytes=new byte[10000];
for (int i=0; i<10000; i++)
{
messageBytes[i]=80;
}
try
{
httpConnection.setRequestProperty("Connection", "Close");
httpConnection.setRequestProperty("Content-Length",
String.valueOf(messageBytes.length));
httpConnection.setRequestProperty("Content-Type",
"text/xml; charset=utf-8");
httpConnection.setRequestMethod("POST");
httpConnection.setDoOutput(true);
httpConnection.setDoInput(true);
}
catch (ProtocolException pe)
{
System.out.println(">>ProtocolException<<");
pe.printStackTrace();
}
OutputStream outputStream=null;
try
{
System.out.println("Getting output stream");
outputStream =httpConnection.getOutputStream();
System.out.println("Got output stream");
outputStream.write(messageBytes);
}
catch (IOException ioe)
{
System.out.println(">>IOException<<");
ioe.printStackTrace();
}
try
{
System.out.println("Getting input stream");
InputStream is=httpConnection.getInputStream();
System.out.println("Got input stream");
byte[] buf = new byte[1000];
int i;
while((i = is.read(buf)) > 0)
{
System.out.println(""+new String(buf));
}
is.close();
}
catch (Exception ie)
{
ie.printStackTrace();
}
}
}
Cheers,
Niels
来源:http://coding.derkeiler.com/Archive/Java/comp.lang.java.programmer/2004-01/3271.html
http://www.weblogicfans.net/viewthread.php?tid=1101
http://forums.sun.com/thread.jspa?threadID=568948
备注:在HttpTimeoutClient类中的第二个构造函数中的:super(url,null,-1)改为super(url,
(String)null,-1)即可。