Java Socket InputStream 阻塞 available() / read()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20552223/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Socket InputStream blocks on available() / read()
提问by Praveen
I'm reading Socket InputStream, calling read() and available() works for few looping iterations. Later available() blocks indefinitely!
我正在阅读 Socket InputStream,调用 read() 和 available() 适用于很少的循环迭代。以后可用()无限期地阻塞!
What could be the issue? How can I make this non-blocking?
可能是什么问题?我怎样才能做到这一点非阻塞?
Code:
代码:
BufferedInputStream buffIn = new BufferedInputStream(in);
while (true)
{
if (buffIn.available() > 0)
{
len = buffIn.read(buffer, 0, buffer.length);
if (len == -1)
{
break;
}
baos.write(buffer, 0, len);
}
}
采纳答案by Rodney
It is not blocking it is spinning.
它没有阻塞它正在旋转。
Once there is no data available you code might as well read
一旦没有可用数据,您也可以阅读代码
while (true)
{
if (buffIn.available() > 0) // ALWAYS false now we've run out of data
{
// unreachable
}
}
The loop will never finish. Your test for the minus 1 value will never be executed when there is no data available.
循环永远不会结束。当没有可用数据时,您对负 1 值的测试将永远不会执行。
You are seeing available() in the stack trace because that's about the only thing in your loop that's taking up any time, so the chances are, when you create you stack trace, that's where it's going to be.
您会在堆栈跟踪中看到 available() ,因为这是循环中唯一占用任何时间的东西,所以很有可能,当您创建堆栈跟踪时,它就会出现在那里。
If you are confident that you will infact get an end-of-file condition (eg if it's TCP and the other end closes the connection) then the available() call is not required at all. Otherwise, you need a different method of determining you have all of the data. For example is the payload size encoded in the first few bytes or something?
如果您确信实际上会得到文件结束条件(例如,如果它是 TCP 并且另一端关闭了连接),则根本不需要 available() 调用。否则,您需要一种不同的方法来确定您拥有所有数据。例如,有效载荷大小是否编码在前几个字节中?
回答by Elliott Frisch
Your code has a pretty big bug; you never did anything with the available
result; so your read
blocks.
你的代码有一个很大的错误;你从未对available
结果做任何事情;所以你的read
积木。
if (buffIn.available() > 0)
{
int amt = (buffIn.available() > buffer.length) ? buffer.length :
buffIn.available();
len = buffIn.read(buffer, 0, amt); // <-- see ternary above.
if (len == -1)
{
break;
}
baos.write(buffer, 0, len);
}
回答by Peter Lawrey
available() is not a good idea for Sockets as it doesn't work as expected. I would use non-blocking NIO in this place.
available() 对 Sockets 来说不是一个好主意,因为它不能按预期工作。我会在这个地方使用非阻塞 NIO。
SocketChannel sc = ...
sc.configureBlocking(false);
ByteBuffer bb = ByteBuffer.allocateDirect(32*1024);
while(sc.read(bb) > 0) {
bb.flip();
while(bb.remaining() > 0 && sc.write(bb) >= 0);
bb.clear();
}
This is quite a bit more efficient than the IO version as it doesn't copy the data into the Java scape just to copy it back out (it saves two copies)
这比 IO 版本更有效,因为它不会将数据复制到 Java scape 中只是为了将其复制回来(它保存了两个副本)
EDITThe canonical version of the loop is follows:
编辑循环的规范版本如下:
while (in.read(bb) > 0 || bb.position() > 0)
{
bb.flip();
out.write(bb);
bb.compact();
}