Socket InputStream blocks on available() / read()

≡放荡痞女 提交于 2021-01-28 04:44:20

问题


I'm reading Socket InputStream, calling read() and available() works for few looping iterations. 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);
    }
}

回答1:


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.

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.

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?




回答2:


available() is not a good idea for Sockets as it doesn't work as expected. I would use non-blocking NIO in this place.

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)

EDIT The canonical version of the loop is follows:

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



回答3:


Your code has a pretty big bug; you never did anything with the available result; so your read blocks.

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


来源:https://stackoverflow.com/questions/20552223/socket-inputstream-blocks-on-available-read

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!