1. IO模型非阻塞 IO

Linux下,可以通过设置socket使其变为 non-blocking。当对一个non-blocking socket执行读操作时,流程是这个样子:

从图中可以看出,当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个error。从用户进程角度讲 ,它发起一个read操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个error时,它就知道数据还没有准备好,于是用户就可以在本次到下次再发起read询问的时间间隔内做其他事情,或者直接再次发送read操作。一旦kernel中的数据准备好了,并且又再次收到了用户进程的system call,那么它马上就将数据拷贝到了用户内存(这一阶段仍然是阻塞的),然后返回。

也就是说非阻塞的 recvform 系统调用调用之后,进程并没有被阻塞,内核马上返回给进程,如果数据还没准备好,
此时会返回一个 error 。进程在返回之后,可以干点别的事情,然后再发起 recvform 系统调用。重复上面的过程,循环往复的进行 recvform 系统调用。这个过程通常被称之为轮询。轮询检查内核数据,直到数据准备好,再拷贝数据到进程,进行数据处理。需要注意,拷贝数据整个过程,进程仍然是属于阻塞的状态。

所以,在非阻塞式 IO 中,用户进程其实是需要不断的主动询问 kernel 数据准备好了没有

非阻塞 IO 示例

服务端


import socket server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1", 8088))
server.listen(5)
server.setblocking(False)
conn_List = [] # 用来存储接受到的客户端连接 while True: # 死循环一直监听
try:
conn, addr = server.accept() # 连接循环
conn_List.append(conn) # 收到了就客户端的反应就加到 conn_List 列表里
print(conn_List)
except BlockingIOError: # 没收到就会抛出异常
conn_del_list = []
conn_send_list = []# 生成两个列表 一个是需要删除的客户端连接 一个是 接受一个要发送数据的连接 还有需要发送的数据 for conn in conn_List: # 循环已经加到 conn_List 列表里的客户端连接
try:
data = conn.recv(1024) # 接收客户端的消息
conn_send_list.append((conn, data))
if not data: # 没有收到就说明客户端连接断开 Linux
conn_del_list.append(conn) # 把没收到的连接放进要删除连接的列表里 注意不能在这里直接remove 因为循环列表过程中改变列表内元素的值 容易造成意外,所以先加到 conn_del_list 里面。
continue
except BlockingIOError: # 这个recv的动作是一个IO操作 所以 可能会卡主 设置False之后会报错 需要捕获异常 接着循环下一个 知道有客户端反应
pass except ConnectionResetError: # window 上的客户端断开异常
conn_del_list.append(conn)
conn_send_del_list = [] # 定义一个发送完数据给客户端需要删除的列表
for conn_send in conn_send_list: # 循环刚刚 收到消息的列表 以及要发送数据的那个元素元素
conn, data = conn_send
try:
conn.send(data.upper()) # send 可能会卡主 需要捕获异常
conn_send_del_list.append(conn_send) 发完消息的conn 加到要删除的列表里 except BlockingIOError:
continue for conn_del in conn_del_list: # 删除刚才再循环中不能删除的conn
conn_List.remove(conn_del)
for conn_send_del in conn_send_del_list:
conn_send_list.remove(conn_send_del)

客户端:


import socket client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("127.0.0.1", 8081)) while True:
msg = input("msg>>:")
client.send(msg.encode("utf8"))
data = client.recv(1024)
print(data.decode("utf8"))

IO模型之非阻塞IO的更多相关文章

  1. Python之阻塞IO模型与非阻塞IO模型

    Python之阻塞IO模型与非阻塞IO模型 IO模型 1 阻塞IO: 全程阻塞 2 非阻塞IO: 发送多次系统调用: 优点:wait for data时无阻塞 缺点:1 系统调用太多 2 数据不是实时 ...

  2. IO模型,非阻塞IO模型,select实现多路复用

    1. IO阻塞模型 IO问题: 输入输出 我要一个用户名用来执行登陆操作,问题用户名需要用户输入,输入需要耗时, 如果输入没有完成,后续逻辑无法继续,所以默认的处理方式就是 等 将当前进程阻塞住,切换 ...

  3. 同步IO与同步非阻塞IO的理解

    本文图片均来自网络 一.同步IO---Blocking IO 在Blocking IO模型中,用户空间的应用程序执行一个系统调用(recvform),这会导致应用程序阻塞,直到数据准备好,并且将数据从 ...

  4. python全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...

  5. 再谈一次关于Java中的 AIO(异步IO) 与 NIO(非阻塞IO)

    今天用ab进行压力测试时,无意发现的: Requests per second:    xxx [#/sec] (mean) ab -n 5000 -c 1000 http://www:8080/up ...

  6. 5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO

    POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...

  7. 同步IO,异步IO,阻塞IO,非阻塞IO

    同步(synchronous):一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行 #所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回.按照这个定义, 其实 ...

  8. 简述同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别

    POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...

  9. 同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别

    POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...

随机推荐

  1. 我也说说Emacs吧(4) - 光标的移动

    在说基本编辑命令之前,我们先加一个小tip,说说如何将函数和键绑定在一起. (define-key global-map [?\C-l] 'recenter-top-bottom) define-ke ...

  2. MongoDB使用笔记

    先创建目录,创建log文件,然后启动服务 cd /d D:\Program Files\MongoDB\Server\3.4\bin\ mongod.exe --dbpath d:\data\db - ...

  3. Java面试题收集以及参考答案(100道)

    不积跬步无以至千里,这里会不断收集和更新Java基础相关的面试题,目前已收集100题. 1.什么是B/S架构?什么是C/S架构 B/S(Browser/Server),浏览器/服务器程序 C/S(Cl ...

  4. Objective C - 2 - 随机数,可变字符串,字符串,SubString

    int main(int argc, const char * argv[]) { @autoreleasepool { NSString *outputString = @"1234567 ...

  5. grunt实现修改代码实时刷新浏览器

    grunt例子:https://github.com/Aquarius1993/gruntDemo grunt 实时刷新1:           1.安装chrome浏览器插件:liveReload ...

  6. postfix邮件服务器搭建02-安装篇

    本文接着上文的环境,进行postfix邮件发信端和dovecot邮件收信端的部署,之后部署基于浏览器的extmail图形管理端,使管理员可以通过网页对邮件虚拟用户进行管理,对邮件服务器进行管控 1.p ...

  7. 使用PullToRefreshListView时遇到Item点击事件失效问题 解决方法

    最近在自己的项目中使用到了以下开源项目: https://github.com/nanchen2251/pullToRefreshDemo 相关介绍博客如下: http://www.cnblogs.c ...

  8. json中的dumps和loads

    常用有2个方法,也是最基本的使用方法: 1.dumps:把字典转成json字符串 进行post的请求的时候就要用json.dumps来进行装换,利用get方法就可以不用了. 2.loads:把json ...

  9. HDU2161

    解题思路:判断素数模板题. #include<cstdio> #include<cstring> #include<algorithm> using namespa ...

  10. php序号发生器,数字重组,可以隐藏原来的1,2,3。。。

    一个晚上的成果,原理: 将1,2,3,4,5,6,7,8,9,0映射到9,5,1,0,4,8,7,3,2,6 同理映射base,base有1-10种数组,也就是可以一位数到10位数 $base 实际上 ...