应用程序研发之网络 - 网络编程模型

用户头像
superman
关注
发布于: 2020 年 07 月 27 日

3:网络编程模型-操作系统对网络编程的封装

3.1 操作系统对网络数据的处理流程

应用程序网络编程面对的都是socket,socket是操作系统对网络模型的抽象。

网络数据到达网卡,网卡做链路层解析,是自己的数据,告知cpu,cpu拷贝到socket缓冲区(内核空间),拷贝完成通知等待读取的应用程序。



3.2 阻塞非阻塞同步与异步

本处:阻塞非阻塞同步异步指操作系统层面。

应用程序进程去读取网络数据的时候分两个阶段

阶段1:询问内核socket缓冲是否有数据(本阶段支持阻塞与非阻塞配置)

阶段2:从内核的socket缓冲区拷贝到用户程序内存

阻塞:发起读请求,如果socket缓冲区没有数据,阻塞线程,有数据后拷贝,返回(等待数据达到,达到后拷贝数据返回)。

非阻塞:读如果缓冲区有数据,拷贝,如果没有返回失败。

多路复用:阶段1一个线程可询问多个socket的状态,关注的socket状态发送变化(主要有数据可读或可写),返回。如果没有任何状态变化阻塞,只到有变化才返回。属于阻塞,不过一个线程关注多个连接,提高了效率。linux 目前主流是用epoll模式。

多路复用的select 是阻塞的

感觉是非阻塞:应用线程读写的时候跟buffer交互,并且读的时候socket已经有数据了,读就比较快。

多路复用配合非阻塞设置

说明:非阻塞只能是第一阶段非阻塞,第二阶段拷贝过程没有非阻塞。

使用多路复用,必须同时将socket设置为非阻塞,这样可以在第一阶段实现用一个线程去获取多个连接的状态(批量做第一阶段的事-看是否有数据)。

多路复用及两阶段



为什么只在第一阶段支持非阻塞

网络io的时候 读写,尤其是读,对方不是不停的写,而是间歇的写。第一阶段如果阻塞会导致线程长时间占用。 而拷贝阶段是内核缓冲区拷贝到用户缓冲区。跟第一阶段相比耗时很短。也没办法拷贝过程中中断。



同理:文件类型的channel在java NIO接口中不支持设置非阻塞。就是因为文件数据本身就在本地,准备阶段的没什么耗时,所以也没必要在接口上支持非阻塞。



应用开发:连接配置为阻塞,用多路服务去select 。



同步与异步:

异步是应用线程告知内核读写后就返回,读写由操作系统完成后告知应用程序。linux目前支持不好。

上述的多路复,阻塞与非阻塞模式都属于同步。

epoll与poll

select|poll 阻塞在所有socket 上,有socket 事件时,唤醒线程,线程自己从socket列表中遍历查找有事件的socket, 如果连接不较多,每次都遍历大量的连接,性能差。

过程模型



epoll

操作系统维护一个eventpoll列表,socket有事件时将自己放入列表,唤醒线程,

线程直接从eventpoll列表里取,取到的就是有事件的socket,避免了遍历。效率高。



应用线程,jdk,系统 间调用流程

是采用epoll还是poll,select 都是系统实现的,应用程序接口是一样的。



3.3 java NIO的封装

java NIO 的新模型

主要引入了Channel ,buffer ,Selector

buffer :

socket缓存区数据大小与应用数据不一样,buffer可方便多读写写,多次读,维护读写共用一个buffer,并互不干扰,相比于原来的流,buffer提供了对数据的结构化访问与读写位置的维护,nio上应用程序读写都在buffer上。

channel:一个channel对应一个socket

Selector:支持多路复用。



参考:

极客时间架构师训练营-李智慧

软件架构设计-余春龙

发布于: 2020 年 07 月 27 日 阅读数: 15
用户头像

superman

关注

还未添加个人签名 2018.07.20 加入

还未添加个人简介

评论

发布
暂无评论
应用程序研发之网络-网络编程模型