最近在一家公司作java實習,寫了個網絡字節採集器。寫了個單例TCPServer來採集數據,其中用到了InputStream.read()來讀取數據。產生了一系列問題,下面作下總結:java
關於while((length = is.read(data)) != -1)問題。網絡
在寫此方法時,產生了一些疑惑,read什麼時候阻塞?什麼時候返回值-1?socket
首先作個假設:測試
一、讀不滿data的length就一直阻塞。爲此,作了如下實驗:spa
Server端:get
byte[] data = new byte[8];it
while((length = is.read(data)) != -1){
String result = new String(data);
System.out.println(result);
System.out.println("length:" + length);
}循環
客戶端:程序
String msg = "ab";方法
byte[] byteMsg = msg.getBytes();
Socket socket = new Socket("127.0.0.1", 9999);
OutputStream out = socket.getOutputStream();
BufferedOutputStream bw = new BufferedOutputStream(out);
for (int i = 0;i<10;i++) {
bw.write(byteMsg);
bw.flush();
}
發現服務端在length=2時,就輸出了,結果爲ab。說明並非在data讀不滿時就一直阻塞。
二、那麼是否是跟flush()有關呢?
下面將bw.flush()注視,發現,並追加代碼Thread.sleep(5*1000),讓它每次輸出2個字節後暫停5秒,以達到網絡不好的目的。發現服務端每次輸出abababab 8個長度的字節。則能夠斷定跟flush有關。
三、那何時緩衝區的數據會flush呢?
和另外一網絡組的程序對接讀數據,他每次都發送148個字節長度的數據,並循環一直髮,而我這邊依次解析148長度的數據。但發現時間久了數據就會對不攏。分析錯誤數據發現是沒有讀完148,而下次再讀時將剩餘沒讀完的部分加在了本次的頭部,當然出錯。因而有個疑問:我這邊每次都是讀148個字節,而後處理,爲何會有讀不滿148的狀況?根據前兩個的測試,初步判斷跟flush有關。多是網絡層數據緩衝區在數據量超過必定範圍時自動flush了。測試以下:
客戶端:
String msg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] byteMsg = msg.getBytes();
try {
Socket socket = new Socket("127.0.0.1", 9999);
OutputStream out = socket.getOutputStream();
BufferedOutputStream bw = new BufferedOutputStream(out);
for (;;) {
bw.write(byteMsg);
//這裏不進行程序flush,一直髮。
}
服務端:
int count = 1000000;
is = socket.getInputStream();
byte[] data = new byte[count];
int length = 0;
while((length = is.read(data)) != -1){
String result = new String(data);
System.out.println(result);
System.out.println("length:" + length);
}
發現輸出以下:
aaaaaaa..............行太長
length:39960
aaaaaaa..............行太長
length:23976
aaaaaaa..............行太長
length:23976
aaaaaaa..............行太長
length:24745
aaaaaaa..............行太長
length:25435
aaaaaaa..............行太長
length:21748
說明網絡層緩衝區在長度必定時,就自動flush,可是這個長度好像不是很固定。長度取決於什麼如今還不清楚。