IO模型说的就是用什么样的通道进行数据的接受以及发送, 想之前的tomcat以及zk 这些有客户端以及服务端的 都会涉及到这块,所以 IO有必要学下,java中支持3中网络io模式 BIO,NIO,AIO.io 模型就是说 客户端和服务端系统通讯的模型
BIO 就是最普通的io
package com.lvhao.bio;import java.io.IOException;
import java.net.Socket;public class SocketClient {public static void main(String[] args) throws IOException {Socket socket = new Socket("127.0.0.1", 9000);//向服务端发送数据socket.getOutputStream().write("HelloServer".getBytes());socket.getOutputStream().flush();System.out.println("向服务端发送数据结束");byte[] bytes = new byte[1024];//接收服务端回传的数据socket.getInputStream().read(bytes);System.out.println("接收到服务端的数据:" + new String(bytes));socket.close();}
}
package com.lvhao.bio;import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;public class SocketServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(9000);while (true) {System.out.println("等待连接。。");//阻塞方法Socket socket = serverSocket.accept();System.out.println("有客户端连接了。。");new Thread(new Runnable() {@Overridepublic void run() {try {handler(socket);} catch (IOException e) {e.printStackTrace();}}}).start();//handler(socket);}}private static void handler(Socket socket) throws IOException {System.out.println("thread id = " + Thread.currentThread().getId());byte[] bytes = new byte[1024];System.out.println("准备read。。");//接收客户端的数据,阻塞方法,没有数据可读时就阻塞int read = socket.getInputStream().read(bytes);System.out.println("read完毕。。");if (read != -1) {System.out.println("接收到客户端的数据:" + new String(bytes, 0, read));System.out.println("thread id = " + Thread.currentThread().getId());}socket.getOutputStream().write("HelloClient".getBytes());socket.getOutputStream().flush();}
}
可以debug走一遍
如果没有客户端连接的话 服务端的这段代码就会阻塞Socket socket  = serverSocket.accept();  //会阻塞  没有客户端连接 服务端会一直卡在这个位置只有有客户端连接 这个服务端 才会跳出阻塞

当服务器Socket socket = serverSocket.accept();  接受到一个socket 实际上接受的就是 客户端执行的这句代码Socket socket = new Socket("127.0.0.1", 9000);// 获取跟服务端连接的socket,然后我拿到这个socket, 我就可以处理这个socket了serverSocket.accept()// 监听客户端的连接
他要把这个socket交给子线程管理,一般线程是由线程池管理的, 因为如果客户端只是连接服务器,他不发送数据的话
服务端这块int read = socket.getInputStream().read(bytes);  read也会阻塞 所以要交给子线程来处理
也就是说此时服务器这边一般做法是来一个请求 开一个线程,来一个请求开一个线程, 这样基本不会有卡死的情况,不会应为第一个Client读数据,写数据慢 而影响后面的Client连接
BIO的问题是在 如果我此时要支撑高并发的一个服务端程序的话,呢么我来了10w 甚至百万的客户端, 此时服务端是开不了呢么多线程的
]所以我们的Bio 连接 没办法支持这种大规模的并发连接
第二 如果你的业务逻辑复杂的话,意味着这个线程会一直耗在服务端
bio 同步阻塞  呢么他的阻塞 体现在哪里  accept以及read方法
nio 非阻塞  意思是我一个线程可以处理多个请求bio场景始和连接数小, 且固定架构
nio场景适合连接数多 的架构
bio 就是我一个client 对应 一个线程
nio 就是 我多个client 最终会注册到select(多路复用器上),我服务器只需要开一个线程就可以同时处理好几个请求

我们先看下服务端代码,前面者3行代码 相当于

意思是我服务端开启了,并且把端口号暴露出去了

就类似于这样,然后接下来
// 创建一个选择器selectorSelector selector = Selector.open();// 把ServerSocketChannel注册到selector上,并且selector对客户端accept连接操作感兴趣ssc.register(selector, SelectionKey.OP_ACCEPT);我创建一个selector 并且把 serversocketchannel注册上去,指定一个事件是Accept(IO事件)意思是告诉selector你需要关注与serversocketchannel 这个channel有关的 的Accept事件。Accept事件是什么东西,我待会如果有一个Client客户端,要来连接我这个端口, 只要一发生连接  selector 就会立马感知到与serversocketchannel 有一个连接请求过来了
写的优点绕
SelectionKey register = ssc.register(selector, SelectionKey.OP_ACCEPT);channel,事件 以及 因为这个channel绑定的selectkey 是一致的 
selector.select();  然后这个方法 是阻塞的 意思是 如果没有事件 发生我就阻塞在那里  ,当有事件发生的时候 我就会跳出阻塞, 看这个事件是什么类型selector.select 方法 监听我们的channel.里面的key                  [阻塞]       你现在没有任何的请求 我就会阻塞 ,监听所有的channel []
如果现在有一个客户端来连接9000端口 [最终连接的就是我们的serverSocketchannel]
serverSocketchannel注册到selector上 . selector 是可以感知这个serverSocketchannel上面有事件发生的
连接一旦建立了  servercocketchannel    身上就会发生一个accept事件SocketChannel sc = ssc.accept();获取到到底是那个一个socketchannel 连接过来的和刚刚这个一样只要有有一个客户端过来连接了,selector就会把他监听到的事件放到selectkey中[然后通过selector,selectorKey的api]就可以拿到他收集的io事件
然后跳出阻塞遍历来处理不同的io事件


我会先判断key是什么状态 [什么事件]如果是连接事件key.getchannel()// 拿到服务器的channel通过key就可以拿到服务器刚刚注册的serversocketchannel然后继而拿到 是那个客户端连接上来的 socketchannel然后我把这个socketchannel 也注册在selector上 并且标注为可读事件通过服务端API accept 拿到客户端的【客户端】socketchannel拿到socketchannel 我就可以做很多事情  比方说读写事件[]

然后这个额selector上面就注册了2个 channel [serversocketchannel[accept], socketchannel[read]]
现在selector会监听所有注册在selector上面的channel,然后会轮询监听这2个channel上面的事件,
假如说现在再有一个client过来连接我这个server,我servercosketchannel上面的事件会发生, 或者说这个client现在要写数据发到服务端,我socketchannel上面就会有读事件发生,
我[selector.select()]就会跳出阻塞,来处理事件只要有事件发生了 我轮询到有事件发生 就会跳出阻塞socketchannel 监听read事件
serversocketchannel  监听ACCEPT事件
//  假设2个都channel都有事件发生的话
selector.select()// 轮循到的集合就有2个key
我拿到2个key 我实际上是逐个去处理
谁先过来 我先处理谁
假设 先[读事件]

苦涩又难理解的IO<1>相关推荐

  1. 苦涩又难理解的IO<2>

    上节我们也说了现在有2个channel注册在selector上.一个是 severSocketChannel 上面的accept事件,一个是socketchannel的read事件 假设我现在 sel ...

  2. 防劝退!数据结构和算法难理解?可视化动画带你轻松透彻理解!

    大家好,我是 Rocky0429,一个连数据结构和算法都不会的蒟蒻- 学过数据结构和算法的都知道这玩意儿不好学,没学过的经常听到这样的说法还没学就觉得难,其实难吗?真难! 难在哪呢?当年我还是个小蒟蒻 ...

  3. Opengl-基本概念-转换矩阵坐标系(最难理解的两章)

    前言 可能这是Opengl学习的时候最难理解的地方,很多人也因为这个地方放弃了.但是我觉得,我们可以不明白有些矩阵是如何推到出来的,但是我们要明白一些简单的矩阵为什么可以做到从一个坐标系到另一个坐标系 ...

  4. python装饰器功能是冒泡排序怎么做_传说中Python最难理解的点|看这完篇就够了(装饰器)...

    https://mp.weixin.qq.com/s/B6pEZLrayqzJfMtLqiAfpQ 1.什么是装饰器 网上有人是这么评价装饰器的,我觉得写的很有趣,比喻的很形象 每个人都有的内裤主要是 ...

  5. Docker 概念很难理解?一文搞定 Docker 端口绑定

    作者 | Dieter Jordens 译者 | 苏本如,责编 | 夕颜 出品 | CSDN(ID:CSDNnews) 以下为译文: 作为初级开发人员的你,是不是参加过这样的面试,在面试中面试官希望你 ...

  6. 聊天机器人最难理解的 10 个词汇

    简评:现在,越来越多的「聊天机器人」凭借着人工智能能与人类对话,甚至编写新闻.人们该如何判断对方是一个血肉之躯,还是一个可笑的算法?又该如何判断一个小说故事是由一台机器编写的,而不是由一位真正的人类作 ...

  7. Javascript之旅——第十站:为什么都说闭包难理解呢?

    原文:Javascript之旅--第十站:为什么都说闭包难理解呢? 研究过js的朋友大多会说,理解了js的原型和闭包就可以了,然后又说这些都是js的高级内容,然后就又扯到了各种神马的作用域...然后不 ...

  8. 【mysql进阶-彩蛋篇】深入理解顺序io和随机io(全网最详细篇)

    MySql系列整体栏目 内容 链接地址 [一]深入理解mysql索引本质 https://blog.csdn.net/zhenghuishengq/article/details/121027025 ...

  9. 西方人很难理解,为什么中国普通人对华为抱有那么大的好感?

    中国人普遍有敝帚自珍的情结,何况华为不是敝帚,比旧扫帚强多了,可能是近现代中国人能拿得出手的少数几个公司,堪比金箍棒. 西方人很难理解,一个在他们眼中威胁通讯安全,很可能在产品中留有技术后门的企业,为 ...

  10. 为什么说爱因斯坦场方程难理解呢,你一看就明白了

    导读:为什么说爱因斯坦场方程难理解呢,你一看就明白了.广义相对论是研究物质引力相互作用的理论,其最本核心的内容就是引力场方程: 为什么说爱因斯坦场方程难理解呢,你一看就明白了 别看这个引力场方程形式上 ...

最新文章

  1. Kotlin setText 使用
  2. 语义分割--DeconvNet--Learning Deconvolution Network for Semantic Segmentation
  3. PHP分页类(较完美)
  4. ARM处理器:开放者的逆袭
  5. 树型控件TreeView的几种用法
  6. openlayer 3 在layer上添加feature
  7. CodeForces - 1514D Cut and Stick(线段树/随机数)
  8. Android下实现GPS定位服务
  9. 推销自己的海盗猫王运营商
  10. LeetCode 1775. 通过最少操作次数使数组的和相等(贪心+双指针)
  11. 【Hadoop 分布式部署 十 一: NameNode HA 自动故障转移】
  12. 非平稳时间序列及建模
  13. 单片机原理及应用C语言实验,《单片机原理及应用》实验指导书.doc
  14. 文本去重:sim哈希算法
  15. ps剪贴蒙版教程(ps创建剪贴蒙版步骤)
  16. 自定义滚动条文档(mCustomScrollbar使用文档)
  17. 【Spikingjelly】SNN框架教程的代码解读_4
  18. 劲爆!有人不用深度学习做强AI?道翰天琼认知智能机器人平台API接口大脑为您揭秘
  19. 模型选择的方法——正则化与交叉验证
  20. 梦幻西游新区服务器维护,梦幻西游2月新区2018 2月新开服务器介绍

热门文章

  1. KGB知识图谱通过数据可视化提升金融行业分析能力
  2. 手游渠道分成的那些坑来等你跳
  3. Win7快速启动栏设置及防止消失方法
  4. 转 OpenGL核心技术之帧缓冲
  5. c语言计算最大值与最小值的差,C语言 · 最大值与最小值计算
  6. 关于工作后定居城市的思考以及房价…
  7. 操作系统虚拟存储管理实验
  8. 如何清理 C 盘空间
  9. 观天利器-stellarium
  10. sql server 不是可以识别的 内置函数名称