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

关于InputStream.read()方法的阻塞原理的测试的更多相关文章

  1. [Android Pro] 关于inputStream.available()方法获取文件的总大小

    reference to :http://hold-on.iteye.com/blog/1017449 如果用inputStream对象的available()方法获取流中可读取的数据大小,通常我们调 ...

  2. (判断url文件大小)关于inputStream.available()方法获取下载文件的总大小

    转自:http://hold-on.iteye.com/blog/1017449 如果用inputStream对象的available()方法获取流中可读取的数据大小,通常我们调用这个函数是在下载文件 ...

  3. Sleeping会话导致阻塞原理(下)

    背景 最近给客户做优化时,有几个客户都存在.SLEEPING 会话中开启了事务,导致的大量阻塞,从而产生严重的性能问题.虽然在之前的文章我分享了Sleeping会话导致阻塞原理(上) .说明了什么是S ...

  4. 机器学习中模型泛化能力和过拟合现象(overfitting)的矛盾、以及其主要缓解方法正则化技术原理初探

    1. 偏差与方差 - 机器学习算法泛化性能分析 在一个项目中,我们通过设计和训练得到了一个model,该model的泛化可能很好,也可能不尽如人意,其背后的决定因素是什么呢?或者说我们可以从哪些方面去 ...

  5. 深入理解java中的底层阻塞原理及实现

    谈到阻塞,相信大家都不会陌生了.阻塞的应用场景真的多得不要不要的,比如 生产-消费模式,限流统计等等.什么 ArrayBlockingQueue, LinkedBlockingQueue, Delay ...

  6. KafkaConsumer 长时间地在poll(long )方法中阻塞

    一,问题描述 搭建的用来测试的单节点Kafka集群(Zookeeper和Kafka Broker都在同一台Ubuntu上),在命令行下使用: ./bin/kafka-topics. --replica ...

  7. DisplayNameFor()方法的工作原理

    DisplayNameFor()方法的工作原理原创Peter Yelnav 最后发布于2018-11-23 11:09:51 阅读数 1308 收藏展开最近研究了一下ASP.NET MVC,困惑于视图 ...

  8. JVM系列-方法调用的原理

    JVM系列-方法调用的原理 最近重新看了一些JVM方面的笔记和资料,收获颇丰,尤其解决了长久以来心中关于JVM方法管理的一些疑问.下面介绍一下JVM中有关方法调用的知识. 目的 方法调用,目的是选择方 ...

  9. go-micro开发RPC服务的方法及其运行原理

    go-micro是一个知名的golang微服务框架,最新版本是v4,这篇文章将介绍go-micro v4开发RPC服务的方法及其运作原理. 基本概念 go-micro有几个重要的概念,后边开发RPC服 ...

随机推荐

  1. Socket 多线程FTP软件开发

    Socket具体还可见360云中文档记载 Socket是一个非常古老的协议了 1970年 Socket.AF_Unix======AF意思是  addressFamily 地址簇 Import os ...

  2. Unity3D使用小技巧

    原地址:http://unity3d.9tech.cn/news/2014/0411/40178.html 1.Crtl+f摄像机自动适配场景. 2.可以用一个立方体作为底盘. 3.人物角色可以直接引 ...

  3. 反正切函数求圆周率 atan

    #define PI atan(1.0)*4 原理:tan ∏/4=1; atan2: 返回给定的 X 及 Y 坐标值的反正切值.反正切的角度值等于 X 轴正方向与通过原点和给定坐标点 (Y坐标, X ...

  4. SQL— CONCAT(字符串连接函数)

    有的时候,我们有需要将由不同栏位获得的资料串连在一起.每一种资料库都有提供方法来达到这个目的: MySQL: CONCAT() Oracle: CONCAT(), || SQL Server: + C ...

  5. Greedy:Radar Installation(POJ 1328)

    装雷达 题目大意,就是令在海岸线的(直线)一边是海(y>0),另一边是陆地(y<=0),在海岸线上装雷达,雷达可以覆盖的范围为d,海上有岛,(x,y),问你应该怎么装雷达,才能做到技能雷达 ...

  6. ipconfig 无效

    刚刚配置了很多的环境变量后,在命令行下输入ipconfig后无效了 于是在环境变量PATH底下再次加入了;C:\WINDOWS\system32; 从新运行ipconfig,问题解决

  7. struts2 <s:property/>标签的使用--输出时间格式转换

    转载地址http://hi.baidu.com/nonyi_com/blog/item/acf1b8d74b6cf63e07088bc4.html 最近在使用struts2的<s:propert ...

  8. SQL 外键

    先新建2个表,写入数据 -- 创建测试主表. ID 是主键. CREATE TABLE test_main ( id INT, value ), PRIMARY KEY(id) ); -- 创建测试子 ...

  9. 归并排序的分析与Java实现

    归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作.归并排序算法依赖归并操作.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.归并排序 ...

  10. Linux中获取当前程序的绝对路径

    代码如下: char current_absolut_path[MAX_SIZE] = ""; memset(current_absolut_path,,MAX_SIZE); // ...