InputStream.read()阻塞
近期打算研究下基于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()阻塞相关推荐
- 记录一次Socket的异常:InputStream.read()阻塞问题
起先是在Socket编程时,服务端取得客户端发送的数据,但是在InputStream.read()的时候,一直停在那,然后取了解了read方法才知道阻塞问题 代码示例: //端口数据取得 byte[] ...
- Android Java 必备:Socket通信
目标 Demo是通过Java ServerSocket 和 Socket 通信实现客户端发送消息和发送文件到服务器,服务器接收到消息和文件,并且实现解决inputStream.read()的阻塞问题思 ...
- java创建阻塞_如何从HttpsURLConnection创建Java非阻塞InputStream?
基本上,我有一个URL,当发布新消息时,该URL在聊天室中流xml更新.我想将URL转换为InputStream并继续读取它,只要保持连接并且没有发送Thread.interrupt().我遇到的问题 ...
- [转]java Socket InputStream 阻塞 问题
第一次写,不好意思,有不对地方多多指出 在Java Socket 编程中,对 InputStream的read()=-1标明流结束,一般按照 Java代码 public byte[] getReq ...
- java inputstream 阻塞_InputStream的阻塞和非阻塞
一.背景 写了一个使用 InputStream 接收 Socket 字节流的 demo ,发现只要 socket 不关闭的情况下读这个InputStream 会一直 block.如果是读的是 File ...
- NSStream线程阻塞处理
http://www.10bay.com/?p=149 [[session inputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] ...
- Java网络编程——11.非阻塞I/O
2019独角兽企业重金招聘Python工程师标准>>> 要允许CPU速度高于网络,传统的Java解决方案是缓冲和多线程.对于相对简单的服务器和客户端,如果不需要非常高的性能,这种方法 ...
- java无阻塞执行脚本,JAVA调用Shell脚本-及阻塞的解决方法
JAVA调用Shell脚本--及阻塞的解决办法 用java调用shell,使用 Process p=Runtime.getRuntime().exec(String[] cmd); Runtime.e ...
- Runtime.getRuntime().exec();里面产生停滞(阻塞,blocking)
Runtime.getRuntime().exec();里面产生停滞(阻塞,blocking) 标签: Process process=Runtime.getRuntime()里面产生停滞 2007- ...
最新文章
- 30+程序员,平时都忙些什么事情?平时都想些什么?以后有啥计划?
- 如何提高做事效率,达成目标协作?
- 【时间序列】最完整的时间序列分析和预测(含实例及代码)
- android中读取properties文件
- 移动项目工作笔记0001---使用uni-app开发移动端应用
- java 文件流 追加_JAVA向文件中追加内容(转)
- 软件测试基础知识大全(新手入门必备)
- 如何在微信公众号的开放平台上运维微信公众号
- 古罗马的幽灵--斗兽场
- Eclipse护眼背景色
- 微信公众号、微信号、微信文章爬虫(搜狗搜索)
- Visual2022安装步骤社区版,专业版or企业版安装(附注册码)(没有桌面图标的解决方法)
- 科技型中小企业认定条件和好处
- 优惠券使用---责任链模式
- 成就亿万富翁的10条规则
- 春招来了!找个互联网IT工作试试看?2021校招公司大全!
- 美东部网站宕机后续:1100万路由器和摄像头仍在公网“裸奔”
- ESP32入门之GPIO:点亮一盏LED灯
- CameraSR----Camera Lens Super-Resolution个人笔记
- python爬虫入门_3种方法爬取古诗文网站
热门文章
- springboot2.彩色日志配置(自用配置ok)
- 英文缩略词——全程及中文含义
- Oracle 10g数据库创建
- 怎么关掉android升级提示,【技巧】手机不停提示软件更新,是更新好还是不更新好?怎么去掉提示?...
- 2018.07.17【省赛模拟】模拟B组 比赛题解(总结)
- FCOS3D: Fully Convolutional One-Stage Monocular 3D Object Detection
- 区间直觉模糊多属性决策方法及matlab应用
- Android自动化测试环境部署及adb sdkmanager avdmanager Monitor DDMS工具使用及命令详解
- WebLogic-ONS configuration failed ONS 配置失败
- ElasticsearchException: Bulk indexing has failures