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