网络IO流

是什么?

        其实就是一系列的数据(分字节流字符流,其实计算机底层识别到的都是二进制数据)。IO流我理解为就是一系列数据在网络之间输入/输出相互交流传递的过程。现实的例子:张三想要从成都传送到北京;那么张三要先进行准备,去传送点,在传输的过程中,只能作为数据(具体怎么传送可以参考影视资料)传送到目的地的相应位置,由北京的那边的专业机构来接收他。在传送的准备-->传送-->接收 整个过程中,就是IO流的实现过程。

网络IO流程:

数据准备   ---> 数据拷贝  

IO网络读取原理:

        网卡(接收到data) --- > 内核 ---> 应用程序(读取),应用程序无法直接访问计算机的硬件,所以中间会加上一个内核(可理解为中间件),可通过socket接口去调用内核,内核去检查网卡找数据;应用程序和内核在运行的过程中,相当于两个进程。那么在计算机的内存中都会开辟相应的空间,来存储数据,内核准备好数据,在内存中直接拷贝到应用程序的内存空间,则此应用程序成功接收到了相应数据。

Linux IO 内核模型:(指应用如何去调用内核的IO函数?阻塞、非阻塞;同步,异步)

阻塞IO(Blocking I/O)  非阻塞IO (Non blocking I/O) IO多路复用(Mulitplexing I/O)

信号驱动(Signal driven I/O)                 ——以上均为同步,前三个最常用

异步IO (Asynchronous I/O)

        同步/异步(synchronous/asynchronous):强调结果返回的形式

        同步是一种可靠的有序运行机制,当我们进行同步操作时,后续的任务是等待当前调用返回,才会进行下一步;而异步则相反,其他任务不需要等待当前调用返回,通常依靠事件、回调等机制来实现任务间次序关系。

        应用去调用内核,需要拿到数据,内核说你先回去,我先找找。过了一会儿,内核找到了,带着数据跑到应用的家里,将数据交给了应用程序(异步),我理解为:IO传输过程中,应用程序需要拿到数据,只需要表达诉求发出需要数据的命令给内核,然后应用该忙啥忙啥,内核找到相应的数据,调用回调接口将数据返回给应用。

        阻塞/非阻塞(blocking/non-blocking):强调对调用端的影响

        Web客户端去调用服务端的过程中,如果一直没有完成访问(服务端启动了,没有客户端连接访问也会进入阻塞状态),未断开连接的情况下,则其他相应的客户端无法来调用此服务端(其他客户端发送消息过来,应用接收不到,当前线程处于阻塞状态,无法从事其他任务)。非阻塞则是Web客户端在调用服务端过程中,另外的客户端依然可以进来调用服务端(因为不管 IO 操作是否结束,直接返回,相应操作在后台继续处理,此时只有一个线程)。——非阻塞IO也会有可能让线程进入阻塞状态。

【        Java NIO和IO之间最大的区别是IO是面向流(Stream)的,NIO是面向块(buffer)的,面向流意味着从流中一次可以读取一个或多个字节,拿到读取的这些做什么你说了算,这里没有任何缓存(这里指的是使用流没有任何缓存,接收或者发送的数据是缓存到操作系统中的,流就像一根水管从操作系统的缓存中读取数据)而且只能顺序从流中读取数据,如果需要跳过一些字节或者再读取已经读过的字节,你必须将从流中读取的数据先缓存起来。

        面向块的处理方式有些不同,数据是先被 读/写到buffer中的,根据需要你可以控制读取什么位置的数据。这在处理的过程中给用户多了一些灵活性,然而,你需要额外做的工作是检查你需要的数据是否已经全部到了buffer中,你还需要保证当有更多的数据进入buffer中时,buffer中未处理的数据不会被覆盖 】

        阻塞IO(BIO)进入到线程阻塞会释放cpu资源(时间片),理想状态下,阻塞IO情况下,其他的socket也没法进入应用,所以资源的释放对于最初的socket任务执行并没有实际帮助,只是存在这种动作而已。     —— 基于线程驱动  1线程:1客户端 

        非阻塞IO(NIO 系统层面的理解) 线程一直循环遍历内核中的内容,一直占用cpu资源会造成cpu异常,java层面理解为:new IO 新的IO体系,有channel,buffer...;NIO优势是规避了多线程问题;弊端:C10K问题,假设有1w个连接,但是只有1个客户端发了消息过来,依然需要向内核发送1w次的recv系统调用,9999次是无意义的,浪费消耗时间和资源。(用户空间向内核空间进行循环遍历,复杂度在系统调用上)

  ——基于事件驱动   1:接收、读、写···

    

IO多路复用(Mulitplexing I/O) 因为NIO的问题,所以出现了多路复用selector(多路复用器——多个客户端通讯的通道)、多个socket事件进来,先由内核去遍历处理,调用Epoll函数(事件切换器/轮询器),做数据准备准备到内核,然后返回状态给selector告知它有个socket进来了(避免了cpu中线程不停占用资源造成的异常);应用程序发起事件处理程序handler() ,调用内核的recvFrom()函数完成数据拷贝。—— 利用了单线程轮询事件的机制,通过高效地定位就绪的 Channel,来决定做什么,仅仅 select 阶段是阻塞的,可以有效避免大量客户端连接时,频繁线程切换带来的问题,应用的扩展能力有了非常大的提高。多路复用器(都是同步的) 三种:select、poll 、epoll;多路复用器只给你状态。select限制了1024个客户端连接,poll没有限制

        select/poll 多路复用器的优势:通过一次系统调用把文件描述符fds传递给内核,内核进行遍历,这个发生在内核内部的遍历,这种遍历减少了系统调用的次数(以前是应用不停遍历所有的连接,C10K问题);弊端:1.重复传递fd  (解决方案:内核开辟空间,保留fd) 2.每次select 、poll内核都会全量遍历fds。后面用epoll

        selector,是 NIO 实现多路复用的基础,它提供了一种高效的机制,可以检测到注册在 Selector 上的多个 Channel 中,是否有 Channel 处于就绪状态,进而实现了单线程对多 Channel 的高效管理。【一条线程去监控多个channels的输入,你可以向一个selector上注册多个channel,然后调用selector的select()方法判断是否有新的连接进来或者已经在selector上注册时channel是否有数据进入。】

NIO高性能之3种并发模型 Reactor  

        Reactor单线程、 Reactor多线程、 Reactor主从模型(多反应堆 列:Tomcat)

具体代码?

        待续···

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Laughing_Xie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值