使用jcifs定义的超时不起作用

时间:2016-07-16 21:38:24

标签: java jcifs

我已将responseTimeout和soTimeout设置为15000ms但我仍然得到了 90000ms后超时。

我在v1.3.18和v1.3.17上进行了测试。

当我没有注册jcifs时,我会发生HttpURLConnection的默认超时 15000ms后正确使用:

connection.setReadTimeout(15000);
connection.setConnectTimeout(15000);

但是当我注册jcifs时,则会在90000ms之后发生时间:

System.setProperty("jcifs.smb.client.responseTimeout", "15000");
System.setProperty("jcifs.smb.client.soTimeout", "15000");
jcifs.Config.registerSmbURLHandler();
[...]
connection.setReadTimeout(15000);
connection.setConnectTimeout(15000);

似乎jcifs超时和我的默认超时都被忽略了 另一个值。

我也直接在Config上尝试了setProperty,但它没有改变:

jcifs.Config.setProperty("jcifs.smb.client.responseTimeout", "15000");
jcifs.Config.setProperty("jcifs.smb.client.soTimeout", "15000");

1 个答案:

答案 0 :(得分:3)

(此消息已发布到jcifs论坛http://thread.gmane.org/gmane.network.samba.java/9554

对我来说问题是jcifs包装了一个新的HttpURLConnection,因此它丢失了原始连接上定义的每个设置,比如超时设置。为了证明这一点,我使用反射或修改库并更改jcifs内部连接,然后超时工作正常。

(有关信息设置jcifs.smb.client.responseTimeout和jcifs.smb.client.soTimeout不起作用)

首先,我验证jcifs是问题:当我使用jcifs.Config.registerSmbURLHandler()时,我的超时15000ms根本不起作用,连接在30000ms后中断。只有当我删除对registerSmbURLHandler()的调用时,我的15000ms超时才有效。

关于这个问题,我打开一个连接(以前注册过jcifs):

URLConnection myConnection = new URL(url).openConnection();

然后URLStreamHandler创建一个包装NtlmHttpURLConnection并隐藏真正的HttpURLConnection:

protected URLConnection openConnection(URL url) throws IOException {
    url = new URL(url, url.toExternalForm(),
            getDefaultStreamHandler(url.getProtocol()));
    return new NtlmHttpURLConnection((HttpURLConnection)
            url.openConnection());
}

所以我的超时设置应用于包装器NtlmHttpURLConnection,它不适用于真正打开的URLConnection。所以我的超时是没用的:

myConnection.setReadTimeout(15000);    // applied to the new NtlmHttpURLConnection(wrapped), not the real wrapped one
myConnection.setConnectTimeout(15000); // applied to the new NtlmHttpURLConnection(wrapped), not the real wrapped one

我可以使用两种解决方案来更改包装连接的超时:使用反射或使用固定库。

通过反射,我访问私有包装连接并更改私有字段connectTimeout和readTimeout:

Class<?> classConnection = myConnection.getClass();

Field privateFieldURLConnection = classConnection.getDeclaredField("connection");
privateFieldURLConnection.setAccessible(true);

URLConnection privateURLConnection = (URLConnection) privateFieldURLConnection.get(myConnection);
Class<?> classURLConnectionPrivate = privateURLConnection.getClass();

Field privateFieldConnectTimeout = classURLConnectionPrivate.getDeclaredField("connectTimeout");
privateFieldConnectTimeout.setAccessible(true);
privateFieldConnectTimeout.setInt(privateURLConnection, 15000);

Field privateFieldReadTimeout = classURLConnectionPrivate.getDeclaredField("readTimeout");
privateFieldReadTimeout.setAccessible(true);
privateFieldReadTimeout.setInt(privateURLConnection, 15000);

或者我修改了jcifs库和构造函数NtlmHttpURLConnection():

public NtlmHttpURLConnection(HttpURLConnection connection) {
    super(connection.getURL());
    this.connection = connection;

    this.connection.setReadTimeout(15000);
    this.connection.setConnectTimeout(15000);

    requestProperties = new HashMap();
}