最近在一家公司做java實習,寫了個網絡字節采集器。寫了個單例TCPServer來采集數據,其中用到了InputStream.read()來讀取數據。產生了一系列問題,下面做下總結:
關於while((length = is.read(data)) != -1)問題。
在寫此方法時,產生了一些疑惑,read何時阻塞?何時返回值-1?
首先做個假設:
1、讀不滿data的length就一直阻塞。為此,做了以下實驗:
Server端:
byte[] data = new byte[8];
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讀不滿時就一直阻塞。
2、那么是不是跟flush()有關呢?
下面將bw.flush()注視,發現,並追加代碼Thread.sleep(5*1000),讓它每次輸出2個字節后暫停5秒,以達到網絡很差的目的。發現服務端每次輸出abababab 8個長度的字節。則可以判定跟flush有關。
3、那什么時候緩沖區的數據會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,但是這個長度好像不是很固定。長度取決於什么現在還不清楚。