IO模型之非阻塞IO
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的更多相关文章
- Python之阻塞IO模型与非阻塞IO模型
Python之阻塞IO模型与非阻塞IO模型 IO模型 1 阻塞IO: 全程阻塞 2 非阻塞IO: 发送多次系统调用: 优点:wait for data时无阻塞 缺点:1 系统调用太多 2 数据不是实时 ...
- IO模型,非阻塞IO模型,select实现多路复用
1. IO阻塞模型 IO问题: 输入输出 我要一个用户名用来执行登陆操作,问题用户名需要用户输入,输入需要耗时, 如果输入没有完成,后续逻辑无法继续,所以默认的处理方式就是 等 将当前进程阻塞住,切换 ...
- 同步IO与同步非阻塞IO的理解
本文图片均来自网络 一.同步IO---Blocking IO 在Blocking IO模型中,用户空间的应用程序执行一个系统调用(recvform),这会导致应用程序阻塞,直到数据准备好,并且将数据从 ...
- python全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)
昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...
- 再谈一次关于Java中的 AIO(异步IO) 与 NIO(非阻塞IO)
今天用ab进行压力测试时,无意发现的: Requests per second: xxx [#/sec] (mean) ab -n 5000 -c 1000 http://www:8080/up ...
- 5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO
POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...
- 同步IO,异步IO,阻塞IO,非阻塞IO
同步(synchronous):一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行 #所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回.按照这个定义, 其实 ...
- 简述同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别
POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...
- 同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别
POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...
随机推荐
- OkHttp之BridgeInterceptor简单分析
在< Okhttp源码简单解析(一) >这篇博客简单分析了Okhttp请求的执行流程,通过该篇博客我们知道OkHttp的核心网络请求中内置"拦截器"发挥了重大作用:本篇 ...
- Jenkins简单的使用
1.每个版本开发提单子,写清楚发布那个项目.配置文件.所执行SQL语句等:QA开始部署测试环境 2.如下时发布项目 一.版本发布 登陆系统,选择对应的项目(以api-gateway为例,如果找不到对应 ...
- visual studio 菜单栏显示异常 插件安装异常 扩展异常修复
这几天在使用Visual studio 的扩展插件的时候,遇见了菜单栏显示异常,解决方案显示异常的问题,如下: 经过自己的一顿摸索,解决方法如下,比如我在安装gitee或github插件之后就出现了这 ...
- emacs编辑器的使用
尽管有许多ide,但是,各种软件使用各种不同,设置等,受不了.觉得应该有一手好的编辑器就可以了.尤其是受不了ide什么lib,.h,exe,dll等路径设置,让人心烦.再加上黑盒子的感觉很不爽.一旦出 ...
- learn go error
package main // 参考文档: // https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/05.2.md im ...
- my_itoa
#include <iostream> using namespace std; char *my_reverse(char* s) { char *p,*q; p=s;q=s; whil ...
- 优化 UWP 中图片的内存占用
跟图片打交道的 UWP 应用或多或少都会遇到图片带来的性能问题,就算不主要处理图片,做个论坛做个新闻客户端都涉及到大量图片.一个帖子.一篇文章里多半都是些高清大图,这些图片一张即可占用程序 1~2M ...
- tableview小结-初学者的问题
初学者的问题主要集中在,下面几个问题: 一.几个函数总是不被调用:例如: - (UIView *)tableView:(UITableView *)tableView viewForHeaderInS ...
- oracle-分区(笔记)
partition by 用于指定分区方式 range 表示分区的方式是范围划分 partition pn 用于指定分区的名字 values less than 指定分区的上界(上限) ------- ...
- flask第十七篇——模板【1】
从这一节开始我们就正式进入flask一个重要的模块——模板了. 我们平时看的知乎平台就是Python开发的,可以看到他的很多页面布局都是一样的,比如你现在搜“如何自学Python”,去知乎看他的页面是 ...