关于InputStream.read()方法的阻塞原理的测试

  最近在一家公司做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,但是这个长度好像不是很固定。长度取决于什么现在还不清楚。

上一篇:bzoj 1191: [HNOI2006]超级英雄Hero 并查集 || 匈牙利算法


下一篇:Eddy's picture(最小生成树)