2011-12-15 182 views
1

在客戶機端,讀碼:的java NIO的SocketChannel讀總是返回相同的數據

byte[] bytes = new byte[50]; //TODO should reuse buffer, for test only 
ByteBuffer dst = ByteBuffer.wrap(bytes); 
int ret = 0; 
int readBytes = 0; 
boolean fail = false; 
try { 
    while ((ret = socketChannel.read(dst)) > 0) { 
    readBytes += ret; 
    System.out.println("read " + ret + " bytes from socket " + dst); 
    if (!dst.hasRemaining()) { 
     break; 
    } 
    } 
    int pos = dst.position(); 
    byte[] data = new byte[pos]; 
    dst.flip(); 
    dst.get(data); 
    System.out.println("read data: " + StringUtil.toHexString(data)); 
} catch (Exception e) { 
    fail = true; 
    handler.onException(e); 
} 

問題是socketChannel.read()總返回正,我檢查返回緩衝器,該數據是重複N次,它喜歡低級套接字緩衝區的位置不會前進。任何想法?

回答

-2

1:這可能不是一個錯誤!

[假設有在緩衝區中讀取數據] ...

你會想到-1在流的末尾...查看http://docs.oracle.com/javase/1.4.2/docs/api/java/nio/channels/SocketChannel.html#read%28java.nio.ByteBuffer%29

如果你不斷recieving一來自read()調用的正值,那麼您將需要確定爲什麼數據不斷被讀取。

當然,這裏的奧祕最終在於源數據(即從中讀取數據的SocketChannel)。

2:你可能存在的問題

如果您的套接字通道是由一個真實的文件,這是有限的來解釋那麼你的文件是非常大的,而最終,讀()操作將返回0。 ..最終......

另一方面,如果您的套接字通道正在偵聽您預期會有限的數據源(例如,序列化的對象流),我會仔細檢查源---也許你的有限流只是產生越來越多的數據......而你正在正確地使用它。

3:最後一點建議

用於調試這種類型的錯誤與ByteBuffer的輸入您的閱讀方法玩把戲:約java.nio中的字節緩衝區的好處是,因爲他們更對象面向較老的byte []編寫器,您可以對其操作進行非常細緻的調試。

+0

感謝您的快速回放。這是連接到Netty服務器的套接字通道。我向服務器發送一個請求,服務器只返回了48個字節,代碼僅在selector.select()返回時執行,並且selectionKey可讀。所以我完全糊塗了。 – 2011-12-15 04:14:46

0

如果服務器僅返回48個字節,則您的代碼必須在read()方法中被阻止,以獲取第49和第50個字節。所以無論是你的'50'是錯的,還是你必須重構你的代碼來讀取和處理你得到的任何東西,而不是先嚐試填充緩衝區。這不可能是你認爲你總是獲得相同數據的代碼。如果您在下一次讀取時重複使用相同的緩衝區,您應該這樣做,但是您的發佈代碼不會執行,那麼對此的解釋將無法壓縮緩衝區。

相關問題