近期打算研究下基于NIO的Netty框架,先来回顾一下I/O的基础。

JAVA里的IO 目前有两种,一种是早期发布的I/O模型,也就是所谓的BIO(Blocking I/O);另一种是JDK1.4里发布的基于 多路复用实现的NIO。

阻塞型 I/O,主要阻塞在两个地方:

第一:在调用InutStream.read 方法是阻塞的,它会一直等到数据到来时(或超时)才会返回;第二:在调用ServerSocket.accept()方法时,也会一直阻塞到有客户端连接才会返回;

目前大部分的客户端服务端的网络应用软件的早期版本的I/O都是使用阻塞型的I/O实现。处理模型参考:

阻塞型的I/O 存在以下几点问题:

首先,InputStream.read()方法在其缓存区未满时,会造成阻塞,只有一定的数据填满了缓存区或者客户端关闭了套接字,方法才会返回。
其次,会产生大量的垃圾,BufferedReader创建了缓存区来从套接字中读入数据,但是同样创建了一些字符串存储这些数据。这些String很快变成垃圾需要回收。
类似的,读写操作被阻塞而且向流中一次写入一个字符会造成效率低下,所以应该使用缓存区,但一旦使用缓存,流又会产生更多是垃圾。
另外,通常在JAVA中处理阻塞I/O要用到线程(大量的线程),一般是实现一个线程池来处理请求。线程使得服务器可以处理多个连接,但是他们同样也引发了许多问题。每个线程拥有
自己的栈空间并且占用一些CPU时间,耗费很大,而且很多时间是浪费了阻塞I/O操作上,没有有效利用CPU.

下面,来看一下阻塞I/O的具体的阻塞情况点:

首先来看一下JAVA文档中的 InputStream 的签名

public abstract class InputStream extends Object implements Closeable

此抽象类是表示字节输入流的所有类的超类。

需要定义 InputStream 的子类的应用程序必须始终提供返回下一个输入字节的方法。

个人理解,这种对象的概念有点像需要数据传输双方之间的一个通道,这个通道负责接收数据(与之对应还有OutPutStream 负责发送数据)。

到目前为止,我所接触到的I/O主要是 File I/O 和 Socket I/O。

InputStream 中的read方法用于读取数据,方法有3个重载。

abstract  int read()
          从输入流读取下一个数据字节。
 int read(byte[] b)
          从输入流中读取一定数量的字节并将其存储在缓冲区数组 b 中。
 int read(byte[] b, int off, int len)
          将输入流中最多 len 个数据字节读入字节数组。

其中InputStream.read()方法,这个方法是从流里每次只读取读取一个字节,效率会非常低。

更好的方法是用InputStream.read(byte[] b)或者InputStream.read(byte[] b,int off,int len)方法,一次读取多个字节。

这里有一点需要特别注意:read 方法在输入数据可用、检测到文件末尾或者抛出异常前,此方法一直阻塞。

这是什么意思呢?

我们来看一个简单的Socket通信的例子:

 【Client】                                                                【ServerSocket】

1、accept()

服务端阻塞,至接收到客户端的请求

2、new Socket("address",port);

建立一个和服务端的socket连接                               接收到客户端连接,accept 阻塞结束

3、socket.getInputStream().read();

从socket请求获取输入流,读取流中的数据。

这个时候问题来了:虽然和客户端的连接好了

但是服务端不知道客户端什么时候会发来数据,

另外,因为网络传输的原因,数据还可能被分

多次到达。结合上面的说明:也就好理解了。

read需要等待输入和输入的到达。

---------------------------------------------------------------------------------------------------------------------------

Socket流这里还存在另外一个问题,socket流和文件流不太一样,文件流很容易知道文件末尾,到了文件末尾,直接就把流close掉就OK了。但是socket 流不一样,你无法知道它什么时候到末尾,所以连接一直保持着,流也一直保持阻塞状态。即使用了带参数的read方法,返回了有效数据,但其实流仍然没有关闭,处于阻塞状态。
针对这种请情况,一般就需要通信的双方约定数据传输的协议了。比如,约定消息的头部首先明确此次传输数据的大小。这样服务端就可以有目的性的读取数据。

---------------------------------------------------------------------------------------------------------------------------

总结一下:

首先,Socket I/O时,发送方如果不将输出流进行关闭,接收方就会认为输入流没有结束,直到超时.
其次,我们判断一个信息是否已经完全的读取完毕,除了使用输入流结束这种办法,还可以自行封装一层协议,用于信息的交互.

这里其实是可以借鉴TCP长连接的实现的:Java当中的Socket类,其实是使用TCP协议进行传输的.

一般情况下,我们会在TCP的基础上再封装一层协议,用户长连接的传输.协议的信息包,也分包头和包体两个部分.
包体,主要就是我们要传输的信息.(维持连接的信息包,包体可为空)
包头,一般分为三个部分.第一部分是信息包的长度(长度一般是指整个信息包的长度);第二部分是包体信息的类型(在这里指出是否是维持连接包);第三部分是信息包的序列号,一般情况下,这个序列号要确保在传输过程中唯一标识该信息包.
如果为了安全起见,还可以在包体后添加包尾,包尾数据用于对包体数据的验证)
这样,通信双方就可以根据包长来判断一次接收的操作是否结束了.

InputStream.read()阻塞相关推荐

  1. 记录一次Socket的异常:InputStream.read()阻塞问题

    起先是在Socket编程时,服务端取得客户端发送的数据,但是在InputStream.read()的时候,一直停在那,然后取了解了read方法才知道阻塞问题 代码示例: //端口数据取得 byte[] ...

  2. Android Java 必备:Socket通信

    目标 Demo是通过Java ServerSocket 和 Socket 通信实现客户端发送消息和发送文件到服务器,服务器接收到消息和文件,并且实现解决inputStream.read()的阻塞问题思 ...

  3. java创建阻塞_如何从HttpsURLConnection创建Java非阻塞InputStream?

    基本上,我有一个URL,当发布新消息时,该URL在聊天室中流xml更新.我想将URL转换为InputStream并继续读取它,只要保持连接并且没有发送Thread.interrupt().我遇到的问题 ...

  4. [转]java Socket InputStream 阻塞 问题

    第一次写,不好意思,有不对地方多多指出 在Java Socket 编程中,对 InputStream的read()=-1标明流结束,一般按照 Java代码   public byte[] getReq ...

  5. java inputstream 阻塞_InputStream的阻塞和非阻塞

    一.背景 写了一个使用 InputStream 接收 Socket 字节流的 demo ,发现只要 socket 不关闭的情况下读这个InputStream 会一直 block.如果是读的是 File ...

  6. NSStream线程阻塞处理

    http://www.10bay.com/?p=149 [[session inputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop]     ...

  7. Java网络编程——11.非阻塞I/O

    2019独角兽企业重金招聘Python工程师标准>>> 要允许CPU速度高于网络,传统的Java解决方案是缓冲和多线程.对于相对简单的服务器和客户端,如果不需要非常高的性能,这种方法 ...

  8. java无阻塞执行脚本,JAVA调用Shell脚本-及阻塞的解决方法

    JAVA调用Shell脚本--及阻塞的解决办法 用java调用shell,使用 Process p=Runtime.getRuntime().exec(String[] cmd); Runtime.e ...

  9. Runtime.getRuntime().exec();里面产生停滞(阻塞,blocking)

    Runtime.getRuntime().exec();里面产生停滞(阻塞,blocking) 标签: Process process=Runtime.getRuntime()里面产生停滞 2007- ...

最新文章

  1. 30+程序员,平时都忙些什么事情?平时都想些什么?以后有啥计划?
  2. 如何提高做事效率,达成目标协作?
  3. 【时间序列】最完整的时间序列分析和预测(含实例及代码)
  4. android中读取properties文件
  5. 移动项目工作笔记0001---使用uni-app开发移动端应用
  6. java 文件流 追加_JAVA向文件中追加内容(转)
  7. 软件测试基础知识大全(新手入门必备)
  8. 如何在微信公众号的开放平台上运维微信公众号
  9. 古罗马的幽灵--斗兽场
  10. Eclipse护眼背景色
  11. 微信公众号、微信号、微信文章爬虫(搜狗搜索)
  12. Visual2022安装步骤社区版,专业版or企业版安装(附注册码)(没有桌面图标的解决方法)
  13. 科技型中小企业认定条件和好处
  14. 优惠券使用---责任链模式
  15. 成就亿万富翁的10条规则
  16. 春招来了!找个互联网IT工作试试看?2021校招公司大全!
  17. 美东部网站宕机后续:1100万路由器和摄像头仍在公网“裸奔”
  18. ESP32入门之GPIO:点亮一盏LED灯
  19. CameraSR----Camera Lens Super-Resolution个人笔记
  20. python爬虫入门_3种方法爬取古诗文网站

热门文章

  1. springboot2.彩色日志配置(自用配置ok)
  2. 英文缩略词——全程及中文含义
  3. Oracle 10g数据库创建
  4. 怎么关掉android升级提示,【技巧】手机不停提示软件更新,是更新好还是不更新好?怎么去掉提示?...
  5. 2018.07.17【省赛模拟】模拟B组 比赛题解(总结)
  6. FCOS3D: Fully Convolutional One-Stage Monocular 3D Object Detection
  7. 区间直觉模糊多属性决策方法及matlab应用
  8. Android自动化测试环境部署及adb sdkmanager avdmanager Monitor DDMS工具使用及命令详解
  9. WebLogic-ONS configuration failed ONS 配置失败
  10. ElasticsearchException: Bulk indexing has failures