Java套接字非阻塞读取

3

我正在使用DataInputStream从套接字中读取字符/数据。

我想要使用.readUnsignedShort();并且如果没有2个字节可读,它应该抛出异常。我应该继承DataInputStream并重写方法以添加异常,还是有更简单的方法?

我正在使用DataInputStream从套接字中读取字符/数据。
我想要使用.readUnsignedShort(),如果没有2个字节可读,它应该抛出异常。我应该继承DataInputStream并重写方法以添加异常,还是有更简单的方法?
4个回答

7
如果你想要快速且简单地实现,可以尝试使用 inputStream.available()
if (stream.available() < 2) {
    // throw it
}

如果您想要真正的非阻塞读取和在数据可用时进行回调,我认为Pablo的答案更好。


1
我通过谷歌搜索“非阻塞套接字”找到了这个,但我真正想要的是在不阻塞线程的情况下轮询套接字以获取传入数据。想想它竟然如此简单,谢谢。 - cib

3

我认为Java NIO非阻塞类是您的最佳选择。请查看SocketChannel类及其相关代码示例。

但要注意,当您发出读取命令时,有可能字节尚未准备好,但这并不意味着它们将永远不会到达套接字...


2
void readButDoNotBlockForALongTime(java.net.Socket socket) {
    int someTimeout = 1000;
    socket.setSoTimeout(someTimeout);
    try {
        // read as much as you want - blocks until timeout elapses
    } catch (java.net.SocketTimeoutException e) {
        // read timed out - you may throw an exception of your choice
    }
}

这是一种简单的方式,只阻止您想要的时间。

setSoTimeout(int超时):启用/禁用具有指定超时(以毫秒为单位)的SO_TIMEOUT。 如果将此选项设置为非零超时,则与此Socket关联的InputStream上的read()调用仅会阻止此时间量。 如果超时到期,则会引发java.net.SocketTimeoutException,尽管Socket仍然有效。 必须在进入阻塞操作之前启用该选项才能生效。 超时必须> 0。 将超时设置为零将解释为无限超时。

对于更优雅的解决方案,您可以考虑使用NIO。


3
每1000毫秒抛出和捕获一个异常,我认为这不够优雅。 - Stealth Rabbi
没错。这比打开程序来进行DOS攻击要好,但使用NIO会更好。 - MauganRa
我同意,@StealthRabbi。移除 "elegant" 这个词。 :) - Zsolt Safrany

0

如果在提供两个字节之前输入结束,它将抛出EOFException异常。 如果没有可用的输入,()将返回零,尽管在某些情况下(例如SSL),它也可以返回零。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接