网络通信-Linux 对网络通信的实现

Linux 网络 IO 模型

同步和异步,阻塞和非阻塞

同步和异步
关注的是调用方是否主动获取结果
         同步:同步的意思就是调用方需要主动等待结果的返回
        异步:异步的意思就是不需要主动等待结果的返回,而是通过其他手段比如,状态通知,
回调函数等。
阻塞和非阻塞
主要关注的是等待结果返回调用方的状态
         阻塞:是指结果返回之前,当前线程被挂起,不做任何事
        非阻塞:是指结果在返回之前,线程可以做一些其他事,不会被挂起。
两者的组合
        1 .同步阻塞: 同步阻塞基本也是编程中最常见的模型,打个比方你去商店买衣服,你去了
之后发现衣服卖完了,那你就在店里面一直等,期间不做任何事(包括看手机),等着商家进
货,直到有货为止,这个效率很低。
        2.同步非阻塞: 同步非阻塞在编程中可以抽象为一个轮询模式,你去了商店之后,发现衣
服卖完了,这个时候不需要傻傻的等着,你可以去其他地方比如奶茶店,买杯水,但是你还
是需要时不时的去商店问老板新衣服到了吗。
        3.异步阻塞: 异步阻塞这个编程里面用的较少,有点类似你写了个线程池,submit 然后马
上 future.get(),这样线程其实还是挂起的。有点像你去商店买衣服,这个时候发现衣服没有
了,这个时候你就给老板留给电话,说衣服到了就给我打电话,然后你就守着这个电话,一
直等着他响什么事也不做。这样感觉的确有点傻,所以这个模式用得比较少。
        4.异步非阻塞: 异步非阻塞。好比你去商店买衣服,衣服没了,你只需要给老板说这是我
的电话,衣服到了就打。然后你就随心所欲的去玩,也不用操心衣服什么时候到,衣服一到,
电话一响就可以去买衣服了

Linux 下的五种 I/O 模型

        总的来说, 阻塞 IO 就是 JDK 里的 BIO 编程,IO 复用就是 JDK 里的 NIO 编程,Linux 下异
步 IO 的实现建立在 epoll 之上,是个伪异步实现,而且相比 IO 复用,没有体现出性能优势,
使用不广。 非阻塞 IO 使用轮询模式,会不断检测是否有数据到达,大量的占用 CPU 的时间,
是绝不被推荐的模型。 信号驱动 IO 需要在网络通信时额外安装信号处理函数,使用也不广
 阻塞 IO 模型

 I/O 复用模型

        比较上面两张图,IO 复用需要使用两个系统调用 (select recvfrom) ,而 blocking IO
调用了一个系统调用 (recvfrom) 。但是,用 select 的优势在于它可以同时处理多个 connection
所以,如果处理的连接数不是很高的话,使用 select/epoll web server 不一定比使用
multi-threading + blocking IO web server 性能更好,可能延迟还更大。 select/epoll 的优势
并不是对于单个连接能处理得更快,而是在于能处理更多的连接。
Linux 代码结构看网络通信

         Linux 内核的源码包含的东西很多,在 Linux 的源代码中,网络设备驱动对应的逻辑位于
driver/net/ethernet, 其中 intel 系列网卡的驱动在 driver/net/ethernet/intel 目录下。 协议栈模
块代码位于 kernel net 目录。
        其中 net 目录中包含 Linux 内核的网络协议栈的代码。子目录 ipv4 ipv6 TCP/IP 协议
栈的 IPv4 IPv6 的实现,主要包含了 TCP UDP IP 协议的代码,还有 ARP 协议、 ICMP
议、 IGMP 协议代码实现,以及如 proc ioctl 等控制相关的代码。
        站在网络通信的角度,源代码组织的表现形式如下:
         网络协议栈是由若干个层组成的,网络数据的流程主要是指在协议栈的各个层之间的传递
一个 TCP 服务器的流程按照建立 socket()函数绑定地址端口 bind()函数侦听端口 listen()
函数接收连接 accept()函数发送数据 send()函数接收数据 recv()函数关闭 socket()函
的顺序来进行。
        与此对应内核的处理过程也是按照此顺序进行的,网络数据内核中的处理过程 主要是在
网卡 协议栈 之间进行 : 从网卡接收数据,交给协议栈处理;协议栈将需要发送的数据通过网络发出去。
        由下图中可以看出,数据的流向主要有两种。应用层输出数据时,数据按照自上而下的顺
序,依次通过应用 API 层、协议层和接口层 ; 当有数据到达的时候,自下而上依次通过接口
层、协议层和应用 API 层的方式,在内核层传递。
        应用层 Socket 的初始化、绑定 (bind) 和销毁是通过调用内核层的 socket() 函数进行资源的申
请和销毁的。
        发送数据的时候,将数据由应用 API 层传递给协议层,协议层在 UDP 层添加 UDP 的首部、
TCP 层添加 TCP 的首部、 IP 层添加 IP 的首部,接口层的网卡则添加以太网相关的信息后,
通过网卡的发送程序发送到网络上。
        接收数据的过程是一个相反的过程,当有数据到来的时候,网卡的中断处理程序将数据从
以太网网卡的 FIFO 对列中接收到内核 , 传递给协议层 , 协议层在 IP 层剥离 IP 的首部、 UDP
剥离 UDP 的首部、 TCP 层剥离 TCP 的首部后传递给应用 API 层,应用 API 层查询 socket
标识后,将数据送给用户层匹配的 socket
        在 Linux 内核实现中,链路层协议靠网卡驱动来实现,内核协议栈来实现网络层和传输层。
内核对更上层的应用层提供 socket 接口来供用户进程访问。

Linux 下的 IO

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

长情知热爱

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

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

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

打赏作者

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

抵扣说明:

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

余额充值