我正在阅读Socket InputStream,调用read()和available()适用于少量循环迭代。以后可用()无限期地阻止!
可能是什么问题?我怎样才能使这种非阻塞?
代码:
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);
}
}
答案 0 :(得分:4)
available()对于套接字不是一个好主意,因为它不能按预期工作。我会在这个地方使用非阻塞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();
}
这比IO版本效率更高,因为它不会将数据复制到Java scape中,只是为了将其复制回来(它可以保存两个副本)
编辑循环的规范版本如下:
while (in.read(bb) > 0 || bb.position() > 0)
{
bb.flip();
out.write(bb);
bb.compact();
}
答案 1 :(得分:3)
它没有阻止它旋转。
一旦没有可用数据,您的代码也可以阅读
while (true)
{
if (buffIn.available() > 0) // ALWAYS false now we've run out of data
{
// unreachable
}
}
循环永远不会完成。当没有可用数据时,将永远不会执行对减1值的测试。
你在堆栈跟踪中看到了available(),因为这是你的循环中唯一占用任何时间的东西,所以当你创建堆栈跟踪时,可能就是它将会是它的位置。
如果您确信您将获得文件结束条件(例如,如果它是TCP而另一端关闭连接),则根本不需要可用()调用。否则,您需要一种不同的方法来确定您拥有所有数据。例如,有效负载大小是在前几个字节中编码的还是什么?
答案 2 :(得分:1)
你的代码有一个很大的错误;你从未对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);
}