java - 如何超时读取Java Socket?

Posted

技术标签:

【中文标题】java - 如何超时读取Java Socket?【英文标题】:How to timeout a read on Java Socket? 【发布时间】:2011-04-04 00:01:34 【问题描述】:

我正在尝试从套接字读取项目,我注意到如果套接字流上没有任何内容,它将停留在读取并备份我的应用程序。我想知道是否有办法设置读取超时或在套接字中没有任何内容一段时间后终止连接。

【问题讨论】:

【参考方案1】:

如果您编写 Java,学习导航 the API documentation 会很有帮助。在socket读取的情况下,可以set the timeout option, e.g.:

socket.setSoTimeout(500);

这将导致与套接字关联的InputStreamread() 调用阻塞半秒后抛出SocketTimeoutException。需要注意的是,SocketTimeoutException 在此类read() 调用引发的异常中是独一无二的,因为套接字仍然有效;你可以继续使用它。异常只是逃避读取并决定是否该做一些不同的事情的一种机制。

while (true) 
    int n;
    try 
        n = input.read(buffer);
    catch (SocketTimeoutException ex) 
        /* Test if this action has been cancelled */
        if (Thread.interrupted()) throw new InterruptedIOException();
    
    /* Handle input... */

【讨论】:

*** 比 API 文档要好得多。请注意这是如何出现在 google 搜索而不是 API 文档中的。 *** 是获得灵感的好地方,但这里的很多信息都不是最理想的,或者完全是错误的。依赖您在此处找到的内容而不通过主要来源或测试进行验证是草率的。【参考方案2】:

如果此套接字是通过URLConnection 创建的以执行网络请求,您可以在读取流之前直接在URLConnection 上设置读取和连接超时:

InputStream createInputStreamForUriString(String uriString) throws IOException, URISyntaxException 
    URLConnection in = new URL(uriString).openConnection();
    in.setConnectTimeout(5000);
    in.setReadTimeout(5000);
    in.setAllowUserInteraction(false);
    in.setDoInput(true);
    in.setDoOutput(false);
    return in.getInputStream();

【讨论】:

setReadTimeout 只会在接收到第一个数据之前超时时引发异常。接收到第一个数据后,即使连接无限挂起也不会发生超时异常。 @ooxi 这完全是错误的。读取超时适用于每次读取,而不仅仅是第一次。【参考方案3】:

是的,应该有一个接受超时值的 Read() 覆盖。通过“覆盖”,我并不是在建议任何人,而是指出他正在使用的套接字方法的覆盖之一采用超时值。

【讨论】:

无论如何,您不会直接从套接字读取,而是从套接字获得InputStream,然后从中读取。照@erikson 说的做,使用setSoTimeout() 不,不应该。这将使SocketInputStream API 与其他流不同。已经有一种方法可以做到这一点,不会破坏InputStream 的可替代性。

以上是关于java - 如何超时读取Java Socket?的主要内容,如果未能解决你的问题,请参考以下文章

网络编程之socket异常总结

JAVA Socket超时浅析(转)

java socket 客户端设置未接收到数据的超时问题

Java -- 如何从 inputStream (socket/socketServer) 中读取未知数量的字节?

Java设置Client Socket链接Server超时时间

可以为Java Socket写消息设置超时吗