新手求助!!httpclient连接超时

hhg0719 2015-08-20 12:00:03
先上错误:

org.apache.http.conn.HttpHostConnectException: Connection to http://121.xx.xxx.116:8082 refused
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:190)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:640)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
at com.cfwx.multichannel.jinjv.http.GetRespFromJinJv.getResp(GetResp.java:90)
at com.cfwx.multichannel.jinjv.test.MainTest.main(MainTest.java:26)
Caused by: java.net.ConnectException: Connection timed out: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
at java.net.Socket.connect(Socket.java:529)
at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:127)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
... 8 more


实现代码(主要部分):

HttpPost httpPost = new HttpPost(Url);
httpPost.setEntity(formEntiry);

HttpResponse httpResponse = null;
HttpClient httpClient = new DefaultHttpClient();
httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,30000);
httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,30000);
try {
httpResponse = httpClient.execute(httpPost);
} catch (ClientProtocolException e) {
logger.error("ClientProtocolException!", e);
} catch (IOException e) {
logger.error("IOException!", e);
}


是这样的,在发200次请求内,都是可以得到返回结果的,但是往200次后,会出现连接超时的错误。
这是什么原因,服务器那边也没有做任何限制。
各位大神帮忙解答一下
...全文
184 点赞 收藏 6
写回复
6 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
hhg0719 2015-08-21
引用 5 楼 zhuangqingch 的回复:
不好意思,“另外1楼和2楼说的设置超时时间,当前楼主的代码不是这个原因导致的,30秒够长了,这里提醒下楼主,如果是超时,则异常会是ConnectTimeoutException(SocketException子类)”描述有误,超时是发生在建立连接阶段,如果超时是抛出SocketTimeoutException 关于网络连接异常,楼主可以看下JDK API,通过异常描述可以大概猜测一些代码问题的产生原因: java.net.SocketTimeoutException(无子类)java.net.SocketException(子类:BindException, ConnectException, NoRouteToHostException, PortUnreachableException )
大神分析的很透彻,真是让小弟收益匪浅。 原因是链接数的问题,查了相关资料,如果不手动释放链接数,得在180s后才会自动释放。 我在代码中手动断开链接,连续发1000次请求都不会报超时的错误。 感谢大神的解答
回复
zhuangqingch 2015-08-20
不好意思,“另外1楼和2楼说的设置超时时间,当前楼主的代码不是这个原因导致的,30秒够长了,这里提醒下楼主,如果是超时,则异常会是ConnectTimeoutException(SocketException子类)”描述有误,超时是发生在建立连接阶段,如果超时是抛出SocketTimeoutException 关于网络连接异常,楼主可以看下JDK API,通过异常描述可以大概猜测一些代码问题的产生原因: java.net.SocketTimeoutException(无子类)java.net.SocketException(子类:BindException, ConnectException, NoRouteToHostException, PortUnreachableException )
回复
zhuangqingch 2015-08-20

/*
 * Class:     java_net_DualStackPlainSocketImpl
 * Method:    waitForConnect
 * Signature: (II)V
 */
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect
  (JNIEnv *env, jclass clazz, jint fd, jint timeout) {
    int rv, retry;
    int optlen = sizeof(rv);
    fd_set wr, ex;
    struct timeval t;
 
    FD_ZERO(&wr);
    FD_ZERO(&ex);
    FD_SET(fd, &wr);
    FD_SET(fd, &ex);
    t.tv_sec = timeout / 1000;
    t.tv_usec = (timeout % 1000) * 1000;
 
    /*
     * Wait for timeout, connection established or
     * connection failed.
     */
    rv = select(fd+1, 0, &wr, &ex, &t);
 
    /*
     * Timeout before connection is established/failed so
     * we throw exception and shutdown input/output to prevent
     * socket from being used.
     * The socket should be closed immediately by the caller.
     */
    if (rv == 0) {
        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
                        "connect timed out");
        shutdown( fd, SD_BOTH );
        return;
    }
 
    /*
     * Socket is writable or error occured. On some Windows editions
     * the socket will appear writable when the connect fails so we
     * check for error rather than writable.
     */
    if (!FD_ISSET(fd, &ex)) {
        return;         /* connection established */
    }
 
    /*
     * Connection failed. The logic here is designed to work around
     * bug on Windows NT whereby using getsockopt to obtain the
     * last error (SO_ERROR) indicates there is no error. The workaround
     * on NT is to allow winsock to be scheduled and this is done by
     * yielding and retrying. As yielding is problematic in heavy
     * load conditions we attempt up to 3 times to get the error reason.
     */
    for (retry=0; retry<3; retry++) {
        NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
                       (char*)&rv, &optlen);
        if (rv) {
            break;
        }
        Sleep(0);
    }
 
    if (rv == 0) {
        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                        "Unable to establish connection");
    } else {
        NET_ThrowNew(env, rv, "connect");
    }
}
回复
zhuangqingch 2015-08-20
执行httpClient.execute(httpPost)会最终会调用JDK自己的API,即调用java.net.DualStackPlainSocketImpl这个类的waitForConnect方法。该方法是一个native方法,具体由C语言实现,通过查看对应的C语言源代码DualStackPlainSocketImpl.c文件,可以看到具体实现如下:

/*
* Class: java_net_DualStackPlainSocketImpl
* Method: waitForConnect
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect
(JNIEnv *env, jclass clazz, jint fd, jint timeout) {
int rv, retry;
int optlen = sizeof(rv);
fd_set wr, ex;
struct timeval t;

FD_ZERO(&wr);
FD_ZERO(&ex);
FD_SET(fd, &wr);
FD_SET(fd, &ex);
t.tv_sec = timeout / 1000;
t.tv_usec = (timeout % 1000) * 1000;

/*
* Wait for timeout, connection established or
* connection failed.
*/
rv = select(fd+1, 0, &wr, &ex, &t);

/*
* Timeout before connection is established/failed so
* we throw exception and shutdown input/output to prevent
* socket from being used.
* The socket should be closed immediately by the caller.
*/
if (rv == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
"connect timed out");
shutdown( fd, SD_BOTH );
return;
}

/*
* Socket is writable or error occured. On some Windows editions
* the socket will appear writable when the connect fails so we
* check for error rather than writable.
*/
if (!FD_ISSET(fd, &ex)) {
return; /* connection established */
}

/*
* Connection failed. The logic here is designed to work around
* bug on Windows NT whereby using getsockopt to obtain the
* last error (SO_ERROR) indicates there is no error. The workaround
* on NT is to allow winsock to be scheduled and this is done by
* yielding and retrying. As yielding is problematic in heavy
* load conditions we attempt up to 3 times to get the error reason.
*/
for (retry=0; retry<3; retry++) {
NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
(char*)&rv, &optlen);
if (rv) {
break;
}
Sleep(0);
}

if (rv == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Unable to establish connection");
} else {
NET_ThrowNew(env, rv, "connect");
}
}

通过代码,可以看出存在2种可能出现的异常:
1、SocketTimeoutException
2、SocketException
第1种异常是发送在建立连接阶段,如连接服务器114.xx.xx.xx:8088,首先会进行与IP地址114.xx.xx.xx建立连接,如果连接失败则会抛SocketTimeoutException异常
第2种异常当建立好连接后,会与服务器的目标端口建立连接,如与端口8088建立连接,当服务器不存在8088这个端口或者该端口的连接数已满时,则会抛出ConnectException(SocketException的子类)异常

所以通过上述分析和代码描述的现象以及抛出的异常信息(前200次正常,超过200失败,异常为ConnectException),楼主的代码是出现了端口连接数已满的问题。端口连接数问题,这个是操作系统本身的硬性限制。限制数根据不同系统而不同。
楼主如果想解决这个问题,可以先查看下是用了什么服务器,通过服务器是可以配置连接数大小的。关于端口连接数限制问题,建立楼主网上查找多了解下。另外1楼和2楼说的设置超时时间,当前楼主的代码不是这个原因导致的,30秒够长了,这里提醒下楼主,如果是超时,则异常会是ConnectTimeoutException(SocketException子类)
希望这些分析能对你有所帮助,如有疑问,欢迎追问。
下面是楼主代码异常栈的调用过程:

回复
你这个超时了啊,请求时间弄长点
回复
兔子托尼啊 2015-08-20
设值时间长点吧。
回复
相关推荐
发帖
Web 开发
创建于2007-09-28

8.0w+

社区成员

Java Web 开发
申请成为版主
帖子事件
创建了帖子
2015-08-20 12:00
社区公告
暂无公告