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="
????????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類中的第二個構造函數(shù)中的:super(url,null,-1)改為super(url,
(String)null,-1)即可。