设置套接字操作超时


86

创建套接字时:

Socket socket = new Socket(ipAddress, port);

因为IP地址不可用,它会引发一个异常,这是可以的。(测试变量whereString ipAddress = "192.168.0.3"int port = 300。)

问题是:如何将该套接字设置为超时?

创建套接字时,如何减少获取aUnknownHostException并使套接字超时之前的时间?


10
@adrianboimvaser:在这种情况下,您应该将其标记为重复项,并留下指向该重复项的注释,以便主持人可以将其关闭(您在一年前就离开了该注释-也许您现在就知道了)。我现在投票赞成这样做,但是我不知道重复的位置在哪里!
汤姆·安德森

1
要继续回复近年来的趋势,@EJP这个问题的标题比复制暧昧更不用说你建议
艾萨克

@Isaac实际上,它根本不是重复的,评论已撤消。
洛恩侯爵,

(请注意:我已经调整了标题,以减少歧义。)
Stephen C

Answers:


165

使用Socket()构造函数connect(SocketAddress endpoint, int timeout)方法代替。

在您的情况下,它将类似于:

Socket socket = new Socket();
socket.connect(new InetSocketAddress(ipAddress, port), 1000);

引用文档

connect

public void connect(SocketAddress endpoint, int timeout) throws IOException

使用指定的超时值将此套接字连接到服务器。零超时被解释为无限超时。然后,连接将被阻塞,直到建立或发生错误。

参数:

endpoint -SocketAddress
timeout要使用的超时值,以毫秒为单位。

抛出:

IOException-如果在连接期间发生错误
SocketTimeoutException-如果超时在连接之前到期
IllegalBlockingModeException-如果此套接字具有关联的通道,并且该通道处于非阻塞模式
IllegalArgumentException-如果端点为null或此套接字不支持SocketAddress子类

从:1.4


4
这可以减少ConnectException的超时(但不会增加),并且对UnknownHostException的超时没有影响,OP声称他正在获取(尽管我不相信)。还要注意,Javadoc在指出默认值是无穷大时是不正确的。不是。该平台的默认超时大约为一分钟,并且无法增加。
洛恩侯爵,

3
即使经过4年,这还是有帮助的,这应该是公认的答案。
Sharp Edge

4
现在已经5年了,这是我在互联网上找到的最佳答案..谢谢
MBH

1
socket.setSoTimeout(timeoutMillis)在阻止IO操作期间要求超时也很重要。
灰色

43

您没有为套接字设置超时,而是为在该套接字上执行的操作设置了超时。

例如 socket.connect(otherAddress, timeout)

socket.setSoTimeout(timeout)用于设置read()操作超时。

参见:http : //docs.oracle.com/javase/7/docs/api/java/net/Socket.html


好吧,在这种情况下,它也是一个连接操作。我找不到任何地方指出该ctor使用无限超时,尽管事实似乎如此。
sandos

3
@sandos在Javadoc中对connect()进行了明确说明。但是,这也是不正确的。默认超时是平台超时,大约一分钟,不是无限,并且只能通过此connect()方法来减少,而不能增加。
洛恩侯爵,

请注意,socket.setSoTimeout必须将其称为AFTER connect,否则它将无效并且读取将永远不会超时。这是一个文档不足的陷阱。
pstanton'9

19

您可以使用以下解决方案:

SocketAddress sockaddr = new InetSocketAddress(ip, port);
// Create your socket
Socket socket = new Socket();
// Connect with 10 s timeout
socket.connect(sockaddr, 10000);

希望能帮助到你!


1
如果按照他的说法,如果他收到UnknownHostException,则它将在第一行发生,该行实际上没有修改的超时。
洛恩侯爵,

但是,第一行不会引发任何异常。从文档中:“将尝试将主机名解析为InetAddress。如果尝试失败,则该地址将被标记为未解析”
2016年

在这种情况下,将通过该connect()方法解决,但不在超时控制下。
罗恩侯爵,

8

由于无法控制超时UnknownHostException。这些是DNS时间。您只能在给定有效主机的情况下控制连接超时。前面的答案都不能正确解决这一点。

但是我很难相信,UnknownHostException当您指定IP地址而不是主机名时,您确实会获得一个。

编辑以控制Java的DNS超时请参阅此答案


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.