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

代码示例:

//端口数据取得
byte[] b = new byte[1024];
in.read(b);//阻塞地方
String contents = new String(b).trim();//trim去除多余空格,否则,读进来的是byte[1024]个占位字节Logger.getLogger(Constant.TASK).info("端口数据取得:" + contents);

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.次接收的操作是否结束了.

可以看一下源码

public abstract class InputStream extends Object implements Closeable

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

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

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

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

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

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

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

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

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

①比如,约定消息的头部首先明确此次传输数据的大小。这样服务端就可以有目的性的读取数据

如果采用一个一个字节读取的话,就需要先两方约定好。不然就会造成read一直在阻塞状态。

②采用InputStrea.shutdownOutput(),在客户端的关闭Stream输出,这样服务端就不会一直在等待输入流的输入

这时候可以采用一次性读取的read(b[])方法,注意的是b[]要不小于传输过来的数据大小,不然只会读取其中一部分。

记录一次Socket的异常:InputStream.read()阻塞问题相关推荐

  1. Socket常见异常场景模拟实战

    前言: 如标题所示,本文主要罗列下Socket编程中的那些常见异常,通过实战的方式来模拟这些异常. 1.java.net.BindException: Address already in use: ...

  2. 记录到日志中的异常栈缺失

    .NET项目中有这样一个场景: 使用反射处理所有业务调用,在反射调用点使用try-catch集中处理异常,并将异常信息记录到日志.其中日志记录是异步的. 问题: 记录到日志中的异常的StackTrac ...

  3. ssm 项目记录用户操作日志和异常日志

    ssm 项目记录用户操作日志和异常日志 参考文章: (1)ssm 项目记录用户操作日志和异常日志 (2)https://www.cnblogs.com/mei-m/p/10231792.html (3 ...

  4. python3 socket 接收 bytes 长度 会变,Python解析Socket数据流异常bytes的问题(详细)...

    本篇文章给大家带来的内容是关于Python解析Socket数据流异常bytes的问题(详细),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. python在通过socket发送数据时, ...

  5. UDP socket 设置为的非阻塞模式

    UDP socket 设置为的非阻塞模式  Len = recvfrom(SocketFD, szRecvBuf, sizeof(szRecvBuf), MSG_DONTWAIT, (struct s ...

  6. 基于MFC的socket编程(异步非阻塞通信)

    对于许多初学者来说,网络通信程序的开发,普遍的一个现象就是觉得难以入手.许多概念,诸如:同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)等,初学者往往迷惑不清,只知其 ...

  7. java socket 异步回调函数_浅谈socket同步和异步、阻塞和非阻塞、I/O模型

    原标题:浅谈socket同步和异步.阻塞和非阻塞.I/O模型 在进行网络编程时,常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式 同步/异步主要针 ...

  8. 记录一次Socket异常:java.net.SocketException: Connection reset

    先贴异常信息 java.net.SocketException: Connection resetat java.net.SocketInputStream.read(SocketInputStrea ...

  9. 异常记录(CPU产生的异常和软件模拟产生的异常)

    文章目录 前奏 异常的分类 CPU产生的异常 软件模拟产生的异常 异常产生 CPU异常的产生 CommonDispatchException函数分析 总结: 软件模拟异常 填充ExceptionRec ...

最新文章

  1. 【深度学习入门到精通系列】模型结构可视化神器Netron(连.pth都可以~!)
  2. 快刀斩“乱码”,你需要这些套路!
  3. 04_查看Android内存使用情况
  4. 【Paddle 经验分享】利用PaddleHub 2.x 完成文本分类训练的坑
  5. javaone_JavaOne 2015 –提交技巧和建议
  6. 前端开发框架_2019年应该如何学习前端开发?
  7. python怎么设计奥运五环_python 相关语法 图形绘制 奥运五环
  8. 想自学python看哪位的视频比较好-python学习视频好的有哪些
  9. 使用bootbox.js(二级务必提交书面和数字到数字中国)
  10. hutool-all 导入Excel 文件 学习笔记
  11. 软考程序员-C专题(1)
  12. 安装 MaxScale
  13. 产业分析:中国电竞行业研究
  14. 到底什么是 路由器(router)、交换机(switch)
  15. 利用python 脚本实现腾讯企业邮箱附件的批量下载
  16. 电商项目_dwd主题域
  17. 试题 算法训练 生活大爆炸版石头剪刀布
  18. 10月份值得关注的10款P2E链游
  19. EEPROM、EPROM、ROM、RAM、FLASH
  20. html 表格中图片显示不全,为何Word 向表格里插入图片时显示不全呢? 有图!

热门文章

  1. C#3.0语法新特性集合
  2. asp动态树菜单集合(3/3)
  3. c++学习笔记之类的应用
  4. (转)谷歌公开dopamine
  5. ./configure 参数解析
  6. 写论文时的一些高大上词句
  7. 将自己数据集转化为lmdb格式
  8. 【编程】位运算(异或)
  9. 科大星云诗社动态20210522
  10. oracle表查询不动怎么转储,Oracle常用的转储方法总结