简体   繁体   English

socket()/ read()上的Socket InputStream块

[英]Socket InputStream blocks on available() / read()

I'm reading Socket InputStream, calling read() and available() works for few looping iterations. 我正在读Socket InputStream,调用read()和available()适用于少量循环迭代。 Later available() blocks indefinitely! 以后可用()无限期地阻止!

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);
    }
}

available() is not a good idea for Sockets as it doesn't work as expected. 对于套接字来说,available()不是一个好主意,因为它不能按预期工作。 I would use non-blocking NIO in this place. 我会在这个地方使用非阻塞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中,只是为了将其复制回来(它保存了两个副本)

EDIT The canonical version of the loop is follows: 编辑循环的规范版本如下:

while (in.read(bb) > 0 || bb.position() > 0)
{
    bb.flip();
    out.write(bb);
    bb.compact();
}

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. 如果您确信您将获得文件结束条件(例如,如果它是TCP而另一端关闭连接),那么根本不需要可用()调用。 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? 例如,在前几个字节中编码的有效负载大小是什么?

Your code has a pretty big bug; 你的代码有一个很大的bug; you never did anything with the available result; 你从来没有对available结果做过任何事情; so your read blocks. 所以你的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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM