Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 插座连接超时上限_Java_Sockets - Fatal编程技术网

Java 插座连接超时上限

Java 插座连接超时上限,java,sockets,Java,Sockets,我正在使用Java套接字。我有一行代码: Socket webSocket = new Socket(); webSocket.connect(new InetSocketAddress(domain, 80), 120000); 指定的超时为120000ms(2分钟)。我很好奇这个超时是否真的被遵守,或者它是否被限制在平台默认连接超时值。另外,如何检查平台的默认连接超时值?换句话说,调用此代码时超时是多少: Socket webSocket = new Socket(domain, 80);

我正在使用Java套接字。我有一行代码:

Socket webSocket = new Socket();
webSocket.connect(new InetSocketAddress(domain, 80), 120000);
指定的超时为120000ms(2分钟)。我很好奇这个超时是否真的被遵守,或者它是否被限制在平台默认连接超时值。另外,如何检查平台的默认连接超时值?换句话说,调用此代码时超时是多少:

Socket webSocket = new Socket(domain, 80);
首先,此超时是否取决于平台?我知道有
SO\u TIMEOUT
,但我认为它只影响
read()
超时,而不影响
connect()


我认为存在默认超时,因为不指定超时值仍然会导致连接超时:connect

默认套接字超时为0,这意味着从不超时。
如果它实际上在x分钟后超时,这意味着它已在代码中设置。在您的情况下是2分钟。

默认套接字超时为0,这意味着从不超时。
如果它实际上在x分钟后超时,这意味着它已在代码中设置。在您的情况下是2分钟。

默认套接字超时为0,这意味着从不超时。
如果它实际上在x分钟后超时,这意味着它已在代码中设置。在您的情况下是2分钟。

默认套接字超时为0,这意味着从不超时。
如果它实际上在x分钟后超时,这意味着它已在代码中设置。就您的情况而言,这是2分钟。

进一步调查,您会发现java连接超时和系统级连接超时之间存在细微的区别

通过更改行:

webSocket.connect(new InetSocketAddress(domain, 80), 120000);
NET_ThrowNew(env, err, "connect");
例如:

webSocket.connect(new InetSocketAddress(domain, 80), 10);
您将看到一个完全不同的异常:
java.net.SocketTimeoutException
,而不是通常的
java.net.ConnectException

Socket.connect()
的实际调用实际上被推迟到一个
SocketImpl
抽象类,以便定义精确的机制。从
Socket
中的
connect()
方法摘录中可以看出:

...
if (!oldImpl)
    impl.connect(epoint, timeout);
else if (timeout == 0) {
    if (epoint.isUnresolved())
        impl.connect(addr.getHostName(), port);
    else
        impl.connect(addr, port);
...
从根本上说,第二个异常(
ConnectException
)是一个依赖于实现的异常,这意味着操作系统本身有一个最大超时时间,该时间在设置java超时时间之前已经达到。进一步探索,在检查
ConnectException
的堆栈跟踪后,我们看到类似的情况(在windows计算机上):

请注意,异常实际上是从本机方法传播的,即从本节传播的(由OpenJDK提供):

该行:

rv = connect(fd, (struct sockaddr *)&sa, sa_len);
实际上是对Winsock2 connect函数的调用,可以查看其MSDN页面。Winsock2套接字本身已设置为默认套接字(
setsockopt
中的
optval
为零)。这意味着它继承了发送和接收的任何系统默认超时。如果连接尝试超过默认超时值,则会在
rv
中出现
SOCKET\u错误
,从而导致线路:

webSocket.connect(new InetSocketAddress(domain, 80), 120000);
NET_ThrowNew(env, err, "connect");
要运行,传播
ConnectException
备份堆栈。(如果您不相信我,请查看OpenJDK源代码中的
DualStackPlainSocketImpl.c

嗯。。。java设置超时到哪里去了?答案是在方法
socketConnect()
下的文件
DualStackPlainSocketImpl.java
中转换到本机层之前的一个堆栈级别,特别是以下片段:

configureBlocking(nativefd, false);
try {
    connectResult = connect0(nativefd, address, port);
    if (connectResult == WOULDBLOCK) {
        waitForConnect(nativefd, timeout);
    }
} finally {
    configureBlocking(nativefd, true);
}
其中,
connect0
是对本机函数的实际调用

本质上,当java出现有限的非零超时时,它会以异步模式启动本机套接字连接,并等待超时过期或本机方法完成,以先发生的为准。设置较大超时值的问题是,本机连接函数本身可能超时并引发
ConnectException
而不是通常的
SocketTimeoutException
。(在Java 8下的特定Windows 10系统上)

同样的练习可以在不同的系统上进行,以确定套接字超时工作的确切机制


tl;医生:


共识是,基本上所有套接字操作都是实现定义的。即使从第一个堆栈层开始,您也会发现,
Socket
将其大部分工作推迟到由操作系统实现的抽象的
SocketImpl
。因此,操作系统完全有可能(如上所述)有更长、更短或完全不存在的超时。从某种意义上说,java超时只有在短于操作系统默认超时(如果有)的情况下才能正常工作,因此您应该准备好处理这两种情况(操作系统因其本机超时而引发异常,而不是java特定超时到期)。

进一步调查,您会发现java连接超时和系统级连接超时之间存在细微的区别

通过更改行:

webSocket.connect(new InetSocketAddress(domain, 80), 120000);
NET_ThrowNew(env, err, "connect");
例如:

webSocket.connect(new InetSocketAddress(domain, 80), 10);
您将看到一个完全不同的异常:
java.net.SocketTimeoutException
,而不是通常的
java.net.ConnectException

Socket.connect()
的实际调用实际上被推迟到一个
SocketImpl
抽象类,以便定义精确的机制。从
Socket
中的
connect()
方法摘录中可以看出:

...
if (!oldImpl)
    impl.connect(epoint, timeout);
else if (timeout == 0) {
    if (epoint.isUnresolved())
        impl.connect(addr.getHostName(), port);
    else
        impl.connect(addr, port);
...
从根本上说,第二个异常(
ConnectException
)是一个依赖于实现的异常,这意味着操作系统本身有一个最大超时时间,该时间在设置java超时时间之前已经达到。进一步探索,在检查
ConnectException
的堆栈跟踪后,我们看到类似的情况(在windows计算机上):

请注意,异常实际上是从本机方法传播的,即从本节传播的(由OpenJDK提供):