[英]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.