【问题标题】:Java HTTPUrlConnection timeout does not workJava HTTPUrlConnection 超时不起作用
【发布时间】:2012-12-11 03:55:45
【问题描述】:

我编写了一个程序,它通过随机代理打开到网站的 httpurl 连接。我的 httpurlconnection 称为 conn。现在我知道,其中一些代理可能太慢了,所以我使用conn.setConnectTimeout(40000)conn.setReadTimeout(40000) 将连接超时设置为 40000 毫秒。

这样做之后,我得到了这个代码:

long diff = 0;
    long starttime = 0;
    long endtime = 0;

    try
    {
        starttime = System.currentTimeMillis();
        conn.connect();

        endtime = System.currentTimeMillis();

        diff = endtime - starttime;

        if (endtime <= starttime + conn.getConnectTimeout())
        {
            //Trying to read sourecode
            InputStreamReader isrConn = new InputStreamReader(conn.getInputStream());
            BufferedReader brConn = new BufferedReader(isrConn);

            line = brConn.readLine();

            while (line != null)
            {

                response += line + "\t";
                try
                {
                    line = brConn.readLine();
                } catch (IOException e)
                {
                    printError("Reading sourcecode failed.");
                }

            }
        }
        else
        {
            response = "blabla.";
        }




    // If conn.connect failed   
    } catch (IOException e)
    {
        endtime = System.currentTimeMillis();
        diff = endtime - starttime;

        response = "Message: "+e.getMessage() +" MyTimeout:"+ conn.getConnectTimeout() +" Actual time passed:  "+ diff;
               e.printStackTrace();


    }

连接失败是有原因的,所以在很多情况下,我会到达最后一个 catch-block 并得到以下输出:


消息:连接超时:连接 MyTimeout:40000 实际经过时间:21012

消息:连接超时:连接 MyTimeout:40000 实际时间已过:21016

消息:连接超时:连接 MyTimeout:40000 实际经过时间:21010

消息:连接超时:连接 MyTimeout:40000 实际经过时间:21009


所以我的问题是:我已将超时设置为 40000 毫秒,但我在大约 21000 毫秒后收到“连接超时”响应,你们中有人知道这是为什么吗?

编辑:我正在使用 Windows 7,我现在将 e.printStackTrace() 添加到 catch-block 中,就像在 cmets 中所说的那样。谢谢到目前为止。现在的输出是(示例):

java.net.ConnectException: Connection timed out: connect
    at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
    at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
    at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
    at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
    at java.net.PlainSocketImpl.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at sun.net.NetworkClient.doConnect(Unknown Source)
    at sun.net.www.http.HttpClient.openServer(Unknown Source)
    at sun.net.www.http.HttpClient$1.run(Unknown Source)
    at sun.net.www.http.HttpClient$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.net.www.http.HttpClient.privilegedOpenServer(Unknown Source)
    at sun.net.www.http.HttpClient.openServer(Unknown Source)
    at sun.net.www.http.HttpClient.<init>(Unknown Source)
    at sun.net.www.http.HttpClient.New(Unknown Source)
    at sun.net.www.http.HttpClient.New(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
    at TestThread.getSourcePage(TestThread.java:361)
    at TestThread.aChecker(TestThread.java:216)
    at TestThread.getNextProxy(TestThread.java:169)
    at TestThread.getNextC(TestThread.java:157)
    at TestThread.aChecker(TestThread.java:273)
    at TestThread.getNextProxy(TestThread.java:169)
    at TestThread.aChecker(TestThread.java:295)
    at TestThread.getNextProxy(TestThread.java:169)
    at TestThread.getNextC(TestThread.java:157)
    at TestThread.run(TestThread.java:103)
    at java.lang.Thread.run(Unknown Source)

Message: Connection timed out: connect MyTimeout:40000 Actual time passed:  21015

【问题讨论】:

  • 请输出并发布实际的堆栈跟踪,而不是您自己的消息。
  • 这可能取决于操作系统,请说明是哪个操作系统
  • 正如 Brian Roach 所说,请将 e.printStackTrace() 的输出发布到 catch 块中。
  • 添加了您所说的内容。我希望你能进一步帮助我,在此先感谢。
  • 21 秒是因为 windows:superuser.com/questions/339959/…(这些值也与 Windows 7 中使用的值相同)。请注意,通常当您设置连接超时时,是因为您希望在比系统默认值更短的时间内超时。

标签: java timeout httpurlconnection urlconnection


【解决方案1】:

看看你得到的异常:
最大的线索:你得到java.net.ConnectException 根据 javadoc,java.net.ConnectException 表示连接被远程拒绝,原因是没有进程正在侦听端口。

public class ConnectException
extends SocketException

Signals that an error occurred while attempting to connect a socket to a remote address and port. 
Typically, the connection was refused remotely (e.g., no process is listening on the remote 
address/port)

您在 HttpUrlConnection 中配置的内容:
连接超时(假设远程端口接受连接)。如果连接超时到期,您将获得 java.net.SocketTimeoutException 而不是 java.net.ConnectException

那么,是什么导致了java.net.ConnectException
我尝试了以下测试用例:

   +------------+------------+----------------+------------------+---------------------------------+ 
   | Valid Host | Valid Port | Valid Proxy IP | Valid Proxy Port | Exception                       | 
   +------------+------------+----------------+------------------+---------------------------------+ 
#1 | yes        | yes        | -NA-           | -NA-             | -- none --                      |
#2 | yes        | no         | -NA-           | -NA-             | java.net.ConnectException       |
   +------------+------------+----------------+------------------+---------------------------------+ 
#3 | yes        | yes        | yes            | yes              | -- none --                      |
#4 | yes        | no         | yes            | yes              | java.net.SocketTimeoutException |
#5 | yes        | yes        | yes            | no               | java.net.ConnectException       |
   +------------+------------+----------------+------------------+---------------------------------+ 
  • 案例 #1、#3 是所有配置都正确的快乐路径
  • 在情况 #4 中,我们得到一个 java.net.SocketTimeoutException,因为 java 进程能够建立连接(到代理端口),但是由于目标主机的端口号无效,所以没有读取任何数据
  • 在 #2、#5 的情况下,我们得到 java.net.ConnectException,因为 java 进程尝试写入/读取的端口无效
  • 连接超时值不适用于没有进程正在侦听 Java 进程尝试连接的端口的情况。这就是您在超时到期之前收到 ConnectException 的原因

Message: Connection refused: connect MyTimeout:10000 Actual time passed: 6549 java.net.ConnectException: Connection refused: connect at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) .... ....

结论:

  • 您尝试连接的某些代理必须关闭。因此java进程抛出java.net.ConnectException
  • 最好捕捉java.net.ConnectException并将代理标记为无效/关闭

【讨论】:

    【解决方案2】:

    根据我的经验,HttpUrlConnection 在名称解析期间不会超时。如果您的设备已经缓存了目标地址,那么它将正确超时。

    出于测试目的,请在代码中使用您的 IP 地址。

    这通常发生在我的移动设备上。

    【讨论】:

      猜你喜欢
      • 2014-01-06
      • 1970-01-01
      • 2017-02-18
      • 1970-01-01
      • 2017-10-25
      • 1970-01-01
      • 2013-01-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多