簡體   English   中英

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

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

我正在讀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);
    }
}

對於套接字來說,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();
}

它沒有阻止它旋轉。

一旦沒有可用的數據,您的代碼也可以閱讀

while (true)
{
    if (buffIn.available() > 0) // ALWAYS false now we've run out of data
    {
       // unreachable
    }
}

循環永遠不會完成。 當沒有可用數據時,將永遠不會執行對減1值的測試。

你在堆棧跟蹤中看到了available(),因為這是你的循環中唯一占用任何時間的東西,所以當你創建堆棧跟蹤時,可能就是它的位置。

如果您確信您將獲得文件結束條件(例如,如果它是TCP而另一端關閉連接),那么根本不需要可用()調用。 否則,您需要一種不同的方法來確定您擁有所有數據。 例如,在前幾個字節中編碼的有效負載大小是什么?

你的代碼有一個很大的bug; 你從來沒有對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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM