<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    MDA/MDD/TDD/DDD/DDDDDDD
    posts - 536, comments - 111, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    Adding Socket Timeout to java.net.URLConnection (JDK 1.2)

    found a bug , see "connected = true;" in public void connect() throws IOException {


    Note: 05/11/01 Sam Found a patch for borland

    As I got the email:

    Just writing to inform you theis patch for 1.3 works with the 1.3 shipped with borland JBuilder 4 (not sure which excat version it is)

    the only problems I had where that the code was a bit messed up, following are the changes made to it to make it work.

    				
    public void SetTimeout(int i)
    throws SocketException
    {
    this.timeout = i; // Should be i not -1 <------------ERROR
    serverSocket.setSoTimeout(i) ;
    }

    public boolean parseHTTP(MessageHeader header, ProgressEntry entry)
    throws java.io.IOException
    {
    if( this.timeout != -1 ) {
    try {
    serverSocket.setSoTimeout(timeout) ; // should be timeout not i <---------------ERROR
    } catch( SocketException e ) {
    throw new java.io.IOException("unable to set socket timeout!") ;
    }
    }

    return super.parseHTTP(header, entry) ;
    }
    Sam

    Under JDK 1.3, which is HTTP 1.1 compatible, the InterruptedIOException gets caught by the socket I/O routines and ignored. input is read in "chunks". I debugged the existing code under 1.3, the Timeout is getting set properly etc., but the exception gets caught in the underlying I/O routines, which have a single retry if any IOExceptions are thrown. Thanks a lot Sun....

    3/22/01: Patch for JDK 1.3 unverified

    Patch code for JDK 1.3 from Matt Ho (unverified)

    				
    ----[ snip ]----

    import sun.net.www.MessageHeader ;
    import sun.net.ProgressEntry ;

    .
    .
    .

    private int timeout = -1 ;

    public void SetTimeout(int i)
    throws SocketException
    {
    this.timeout = -1 ;
    serverSocket.setSoTimeout(i) ;
    }

    public boolean parseHTTP(MessageHeader header, ProgressEntry entry)
    throws java.io.IOException
    {
    if( this.timeout != -1 ) {
    try {
    serverSocket.setSoTimeout(i) ;
    } catch( SocketException e ) {
    throw new java.io.IOException("unable to set socket timeout!") ;
    }
    }

    return super.parseHTTP(header, entry) ;
    }

    ----[ snip ]----

    On with the rest of the stuff

    The BSD socket API supports a timeout option (the option is SO_TIMEOUT), which is also supported in java.net.socket. Unfortunately, java.net.URLConnection does not expose the underlying socket. So if you have a URL connection that attempts to connect to a dead URL (i.e., the URL is well formed and exists but the site is down), the socket will eventually timeout using the operating system's default timeout (420 seconds on Win NT). The timeout is a very long time, e.g., for spiders or URL checking.

    The following files illustrate a technique to introduce a socket timeout to URL connection, based upon the actual java source code itself (see the open source community licensing at JavaSoft).

    The Base classes, or URLConnection internals

    Java's implementation of networking is protocol independent, as well as object oriented. Therefore the implementation is not as straightfoward as one might imagine.

    URLConnection relies upon several internal classes using a client/server model as well as a "factory" design pattern. The client's base class is sun.net.www.http.HttpClient. This class is extended for the purpose of exposing the socket.

    The default factory is URLStreamHandlerFactory, which indirectly "handles" the creation of an HTTP client by instantiating a class that is specific to the HTTP protocol: sun.net.www.protocol.http.Handler. The handler actually creates the client.

    In practice, the factory is only necessary to mimic java's implementation, but only the Handler is really needed.

    Derived Classes

    We derive 4 classes so as to preserve the symmetry with the java source code:

    HttpURLConnectionTimeout extends sun.net.www.protocol.http.HttpURLConnection
    HttpTimeoutHandler extends sun.net.www.protocol.http.Handler
    HttpTimeoutFactory implements java.net.URLStreamHandlerFactory
    HttpClientTimeout extends sun.net.www.http.HttpClient

    On with the source code.


    HttpURLConnectionTimeout

    // whatever package you want
    import sun.net.www.http.HttpClient;
    import java.net.*;
    import java.io.*;
    public class HttpClientTimeout extends HttpClient
    {
    public HttpClientTimeout(URL url, String proxy, int proxyPort) throws IOException
    {
    super(url, proxy, proxyPort);
    }

    public HttpClientTimeout(URL url) throws IOException
    {
    super(url, null, -1);
    }

    public void SetTimeout(int i) throws SocketException {
    serverSocket.setSoTimeout(i);
    }

    /* This class has no public constructor for HTTP. This method is used to
    * get an HttpClient to the specifed URL. If there's currently an
    * active HttpClient to that server/port, you'll get that one.
    *
    * no longer syncrhonized -- it slows things down too much
    * synchronize at a higher level
    */
    public static HttpClientTimeout GetNew(URL url)
    throws IOException {
    /* see if one's already around */
    HttpClientTimeout ret = (HttpClientTimeout) kac.get(url);
    if (ret == null) {
    ret = new HttpClientTimeout (url); // CTOR called openServer()
    } else {
    ret.url = url;
    }
    // don't know if we're keeping alive until we parse the headers
    // for now, keepingAlive is false
    return ret;
    }

    public void Close() throws IOException
    {
    serverSocket.close();
    }

    public Socket GetSocket()
    {
    return serverSocket;
    }


    }

    HttpTimeoutFactory

    import java.net.*;

    public class HttpTimeoutFactory implements URLStreamHandlerFactory
    {
    int fiTimeoutVal;
    public HttpTimeoutFactory(int iT) { fiTimeoutVal = iT; }
    public URLStreamHandler createURLStreamHandler(String str)
    {
    return new HttpTimeoutHandler(fiTimeoutVal);
    }

    }

    HttpTimeoutHandler

    import java.net.*;
    import java.io.IOException;

    public class HttpTimeoutHandler extends sun.net.www.protocol.http.Handler
    {
    int fiTimeoutVal;
    HttpURLConnectionTimeout fHUCT;
    public HttpTimeoutHandler(int iT) { fiTimeoutVal = iT; }

    protected java.net.URLConnection openConnection(URL u) throws IOException {
    return fHUCT = new HttpURLConnectionTimeout(u, this, fiTimeoutVal);
    }

    String GetProxy() { return proxy; } // breaking encapsulation
    int GetProxyPort() { return proxyPort; } // breaking encapsulation

    public void Close() throws Exception
    {
    fHUCT.Close();
    }

    public Socket GetSocket()
    {
    return fHUCT.GetSocket();
    }
    }

    HttpURLConnectionTimeout

    import java.net.*;
    import java.io.*;
    import sun.net.www.http.HttpClient;

    public class HttpURLConnectionTimeout extends sun.net.www.protocol.http.HttpURLConnection
    {
    int fiTimeoutVal;
    HttpTimeoutHandler fHandler;
    HttpClientTimeout fClient;
    public HttpURLConnectionTimeout(URL u, HttpTimeoutHandler handler, int iTimeout) throws IOException
    {
    super(u, handler);
    fiTimeoutVal = iTimeout;
    }

    public HttpURLConnectionTimeout(URL u, String host, int port) throws IOException
    {
    super(u, host, port);
    }

    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 = HttpClientTimeout.GetNew(url);
    }
    fClient = (HttpClientTimeout)http;
    ((HttpClientTimeout)http).SetTimeout(fiTimeoutVal);
    } else {
    // make sure to construct new connection if first
    // attempt failed
    http = new HttpClientTimeout(url, fHandler.GetProxy(), fHandler.GetProxyPort());
    }
    ps = (PrintStream)http.getOutputStream();
    } catch (IOException e) {
    throw e; }
    // this was missing from the original version
    connected = true;
    }

    /**
    * Create a new HttpClient object, bypassing the cache of
    * HTTP client objects/connections.
    *
    * @param url the URL being accessed
    */
    protected HttpClient getNewClient (URL url)
    throws IOException {
    HttpClientTimeout client = new HttpClientTimeout (url, (String)null, -1);
    try {
    client.SetTimeout(fiTimeoutVal);
    } catch (Exception e)
    { System.out.println("Unable to set timeout value"); }
    return (HttpClient)client;
    }

    /**
    * opens a stream allowing redirects only to the same host.
    */
    public static InputStream openConnectionCheckRedirects(URLConnection c)
    throws IOException
    {
    boolean redir;
    int redirects = 0;
    InputStream in = null;

    do {
    if (c instanceof HttpURLConnectionTimeout) {
    ((HttpURLConnectionTimeout) c).setInstanceFollowRedirects(false);
    }

    // We want to open the input stream before
    // getting headers, because getHeaderField()
    // et al swallow IOExceptions.
    in = c.getInputStream();
    redir = false;

    if (c instanceof HttpURLConnectionTimeout) {
    HttpURLConnectionTimeout http = (HttpURLConnectionTimeout) c;
    int stat = http.getResponseCode();
    if (stat >= 300 && stat <= 305 &&
    stat != HttpURLConnection.HTTP_NOT_MODIFIED) {
    URL base = http.getURL();
    String loc = http.getHeaderField("Location");
    URL target = null;
    if (loc != null) {
    target = new URL(base, loc);
    }
    http.disconnect();
    if (target == null
    || !base.getProtocol().equals(target.getProtocol())
    || base.getPort() != target.getPort()
    || !HostsEquals(base, target)
    || redirects >= 5)
    {
    throw new SecurityException("illegal URL redirect");
    }
    redir = true;
    c = target.openConnection();
    redirects++;
    }
    }
    } while (redir);
    return in;
    }

    // Same as java.net.URL.hostsEqual


    static boolean HostsEquals(URL u1, URL u2)
    {
    final String h1 = u1.getHost();
    final String h2 = u2.getHost();

    if (h1 == null) {
    return h2 == null;
    } else if (h2 == null) {
    return false;
    } else if (h1.equalsIgnoreCase(h2)) {
    return true;
    }
    // Have to resolve addresses before comparing, otherwise
    // names like tachyon and tachyon.eng would compare different
    final boolean result[] = {false};

    java.security.AccessController.doPrivileged(
    new java.security.PrivilegedAction() {
    public Object run() {
    try {
    InetAddress a1 = InetAddress.getByName(h1);
    InetAddress a2 = InetAddress.getByName(h2);
    result[0] = a1.equals(a2);
    } catch(UnknownHostException e) {
    } catch(SecurityException e) {
    }
    return null;
    }
    });

    return result[0];
    }

    void Close() throws Exception
    {
    fClient.Close();
    }

    Socket GetSocket()
    {
    return fClient.GetSocket();
    }
    }

    Sample Usage #1

    import java.net.*;
    public class MainTest
    {

    public static void main(String args[])
    {
    int i = 0;
    try {
    URL theURL = new URL((URL)null, "http://www.snowball.com", new HttpTimeoutHandler(150)); // timeout value in milliseconds

    // the next step is optional
    theURL.setURLStreamHandlerFactory(new HttpTimeoutFactory(150));


    URLConnection theURLconn = theURL.openConnection();
    theURLconn.connect();
    i = theURLconn.getContentLength();
    }
    catch (InterruptedIOException e)
    {
    System.out.println("timeout on socket");
    }
    System.out.println("Done, Length:" + i);
    }
    }

    Sample Usage #2

    		try
    {
    HttpTimeoutHandler xHTH = new HttpTimeoutHandler(10); // timeout value in milliseconds
    URL theURL = new URL((URL)null, "http://www.javasoft.com", xHTH);
    HttpURLConnection theUC = theURL.openConnection();
    .
    .
    .
    }
    catch (InterruptedIOException e)
    {
    // socket timed out

    }

    Some remarks: this code is thread safe.

    More to come

    來源:http://www.logicamente.com/sockets.html

    ???? http://www.edevs.com/java-programming/15068/


    Thanks Felipe!

    If I understand information at http://www.logicamente.com/sockets.html correctly there are 2 problems with timeout when using HttpURLConnection in JDK 1.3:

    1. HttpURLConnection does not allow changing the default timeout that is in order of few minutes.

    2. If actual HTTP stream is chunked then HttpURLConnection ignores even the default timeout and tries to read what it perceives as a continued stream resulting in indefinite read wait.

    The patch shown at the above URL, consisting of subclassing of 4 system classes (1 from java.net... and 3 from sun.net.www...), is aimed to resolve problem 1 above but does not help in problem 2.

    My main problem is to have timeout when reading chunked stream (system default timeout will be ok to beginning with) and therefore the question is if this bug has been corrected in later versions of JDK? Thanks.

    -----

    I have seen much chat about this "problem", that is setSoTimeout not available or not working properly.

    how about you write your own Timer (resettable) or 1.4 has Timer class

    you just reset it anytime you detect network activity and close the Socket if the Timer finishes its cycle?

    主站蜘蛛池模板: 最近免费中文字幕mv在线电影| 一级毛片在线免费播放| 99视频免费观看| 亚洲av最新在线网址| 在线观看肉片AV网站免费 | 成年女人毛片免费观看97| 亚洲午夜久久久久久尤物| 国产成人免费午夜在线观看| 亚洲黑人嫩小videos| h视频在线免费看| 亚洲最大的成人网站| 四虎影在线永久免费观看| 高h视频在线免费观看| 最新亚洲成av人免费看| 日韩精品无码免费专区午夜| 日韩精品亚洲人成在线观看| 爱情岛亚洲论坛在线观看 | 国产亚洲综合一区柠檬导航| 免费看黄的成人APP| 亚洲国产精品人久久| 国产男女爽爽爽爽爽免费视频 | 噜噜综合亚洲AV中文无码| 久久精品国产精品亚洲人人| 99在线免费视频| 亚洲免费闲人蜜桃| 日本人护士免费xxxx视频| 久久毛片免费看一区二区三区| 亚洲日本中文字幕| 永久中文字幕免费视频网站| 人禽伦免费交视频播放| 亚洲午夜视频在线观看| 巨胸喷奶水视频www网免费| 乱爱性全过程免费视频| 亚洲视频一区网站| 日韩免费视频一区| 国产成人精品一区二区三区免费| 亚洲综合色7777情网站777| 亚洲毛片网址在线观看中文字幕| 在线人成精品免费视频| 国产精品亚洲精品日韩电影| 久久久久亚洲Av片无码v|