上文描述了最简易的非阻塞IO,采用的是轮询的方式,这节我们使用IO复用模型。

 

阻塞IO

 

过去我们使用IO复用与阻塞IO结合的时候,IO复用模型起到的作用是并发监听多个fd。

以简单的回射服务器为例,我们只监听了某fd是否可读,一旦fd有数据,我们立刻read,然后将其write给对方。

在阻塞IO里面,我们总是认为fd是可写的。因为即使底层的IO缓冲区已满,稍微等待片刻即可。这与read卡在一个无数据的fd上是两种情况。所以从这个角度出发,是不需要监听fd的写事件的。

总之,在阻塞IO中,收到数据然后write,这二者是同时使用的。

 

非阻塞IO

 

到了非阻塞IO里面,事情就远远不是这么简单了。此时,IO绝不仅仅是并发监听fd。

因为在这种情况下,如果某fd的write缓冲区满了,write会立刻返回-1,并且返回EWOULDBLOCK。所以数据的收和发未必可以同时进行,所以对于write操作,我们需要一个buffer来暂存数据。当fd可写时,才可以写入数据。

对于read一端,同样需要一个buffer,原因是因为,在阻塞IO中,假设双方协定好处理分包问题,对方发过来一个len为4000,然后我们需要调用readn函数确保收到足够的4000字节,这其中由于网络的拥塞,readn内部可能需要调用多次read系统调用。所以这中间需要短暂的等待。

到了非阻塞IO中,无法再使用readn反复调用read,否则就变成了轮询操作。如果数据收不满咋办?需要暂存起来,放到一个buffer中,由用户手工处理信息。

综上,非阻塞IO的read和write端都需要buffer

详细的叙述请参考muduo库作者陈硕的Muduo 设计与实现之一:Buffer 类的设计

 

Buffer的设计

 

Buffer肯定要有输入和输出,所以我设计buffer的格式如下:

readindex表示要从Buffer中读取数据的起始位置。writeIndex则表示向Buffer中存放数据的起点。所以writeIndex – readIndex 是Buffer中数据的大小,而end – writeIndex 则表示Buffer中剩余的空间。

注意,每当buffer中的数据读完时,我们便重置指针,readIndex = writeIndex = begin。

 

使用非阻塞IO编写回射服务器的客户端

 

这里的逻辑是:用户从stdin输入数据,然后发给sockfd,随后从sockfd接收数据,输出给stdout。

所以这里我们要监听四次,stdin的读事件,sockfd的读和写事件,stdout的写事件。

注意这里需要两个buffer,因为存在两个数据流:

stdin  -> Buffer –> sockfd

sockfd –> Buffer –> stdout

所以我们用到两个缓冲区:

一个用于向sockfd发送数据。

一个用于从sockfd接收数据。

 

后续将持续讲解Non-Blocking IO,直到完成完整的客户端和服务端。

未完待续。

Linux非阻塞IO(二)网络编程中非阻塞IO与IO复用模型结合的更多相关文章

  1. Java IO、网络编程、NIO、Netty、Hessian、RPC、RMI的学习路线

    好久没看Java IO这块的内容,感觉都快忘得差不多了.平成编程也没有设计到太多的Java基础知识,所以这里希望可以抽点时间回顾一下,让艾宾浩斯记忆曲线不要下降的太快. 回顾这个主要还是以总结为主,能 ...

  2. linux下C语言socket网络编程简例

    原创文章,转载请注明转载字样和出处,谢谢! 这里给出在linux下的简单socket网络编程的实例,使用tcp协议进行通信,服务端进行监听,在收到client的连接后,发送数据给client:clie ...

  3. 网络编程技术-----6、I/O复用实现并发服务器

    网络编程技术-----6.I/O复用实现并发服务器 一.实验要求 服务器:     服务器等待接收客户的连接请求,一旦连接成功则显示客户地址,接着接收客户端的名称并显示:然后接收来自该客户的字符串,对 ...

  4. UNIX网络编程 第6章 I/O复用:select和poll函数

    UNIX网络编程 第6章 I/O复用:select和poll函数

  5. Python网络编程(http协议,IO多路复用、select内核监听)

    前言: 什么是IO? 分为IO设备和IO接口两个部分 如Linux系统,I/O操作可以有多种方式 比如DIO(DirectI/O) AIO(AsynchronousI/O异步I/O) Memory-M ...

  6. Java网络编程 -- BIO 阻塞式网络编程

    阻塞IO的含义 阻塞(blocking)IO :阻塞是指结果返回之前,线程会被挂起,函数只有在得到结果之后(或超时)才会返回 非阻塞(non-blocking)IO :非阻塞和阻塞的概念相对应,指在不 ...

  7. Linux Linux程序练习十一(网络编程大文件发送UDP版)

    //网络编程发送端--大文件传输(UDP) #include <stdio.h> #include <stdlib.h> #include <string.h> # ...

  8. Linux Linux程序练习十(网络编程大文件发送)

    //网络编程客户端--大文件传输 #include <stdio.h> #include <stdlib.h> #include <string.h> #inclu ...

  9. linux驱动开发学习二:创建一个阻塞型的字符设备

    在Linux 驱动程序中,可以使用等待队列来实现阻塞进程的唤醒.等待队列的头部定义如下,是一个双向列表. struct list_head { struct list_head *next, *pre ...

随机推荐

  1. Android四大组件:Service

    前言 Service作为Android四大组件之一,应用非常广泛 本文将介绍对Service进行全面介绍(基础认识.生命周期.使用和应用场景) 目录 目录 1. 基础知识 定义:服务,属于Androi ...

  2. [ CodeVS冲杯之路 ] P1048

    不充钱,你怎么AC? 题目:http://codevs.cn/problem/1048/ 区间DP题,设 f[i][j] 为在区间 [i,j] 中合并的最小代价 目标状态是 f[1][n],末尾的求和 ...

  3. WIN8下笔记本共享热点的设置

    C:\windows\system32>netsh wlan start hostednetwork 无法启动承载网络. 组或资源的状态不是执行请求操作的正确状态. 解决方法: http://j ...

  4. 基于Xen实现一种domain0和domainU的应用层数据交互高效机制 - 3

    继续 上一篇 的研究,结合 xen4.2.3 的代码分析,发现 xen4.2.3 的应用层工具库 tools 包含一个工具叫 libvchan ,其头文件描述如下: * This is a libra ...

  5. CSS控制图片显示区域

    优化页面响应速度,减少页面向服务端请求图片次数,有时候可能会将多个小图合并到一张图中,用的时候通过css控制显示的区域,比如:上传一张人物图片到服务器检测人脸,最后在页面上列出所有识别出来的人脸,实现 ...

  6. js面试总结

    <div id="app"> <button onClick="app()">点击1</button> <button ...

  7. 如何跳转到其他APP(android)

    有很多小伙伴会遇上这样的需求,从自己的app页面跳转到其他APP界面,一般情况下都是在自己的主包中跳转到公司其他APP,或者是合作方的APP,如果手机中没有这款APP会下载这款APP . 今天,博主就 ...

  8. POJ 2689.Prime Distance-区间筛素数

    最近改自己的错误代码改到要上天,心累. 这是迄今为止写的最心累的博客. Prime Distance Time Limit: 1000MS   Memory Limit: 65536K Total S ...

  9. UVALive 3027 Corporative Network (带权并查集)

    题意: 有 n 个节点,初始时每个节点的父节点都不存在,你的任务是执行一次 I 操作 和 E 操作,含义如下: I  u  v   :  把节点 u  的父节点设为 v  ,距离为| u - v | ...

  10. Nginx配置文件分析

    #user nobody; #启动进程数,即启动ngnix服务的个数,通常设置和cpu的数量相等 worker_processes 1; #全局错误日志及PID文件 #error_log logs/e ...