# django不是一个异步框架
# tornado是异步的web框架
# 处理每秒大量的请求 # 个人理解的IO:就是应用层与内核驱动层的交互,这个过程无论从应用层到内核中,还是驱动层等待硬件层的数据,都是需要时间的,这个过程是IO操作过程 # 五种IO Model
# blocking IO 阻塞IO
# nonblocking 非阻塞IO
# IO multiplexing IO多路复用
# signal driven IO 信号驱动IO
# asynchronous IO 异步IO
# 在python中没有提供异步IO的机制,没有操作系统将数据直接给应用层的获取到数据的接口. 但是由很多python的异步框架
# 这种异步IO机制其实是很好的
# IO发生时涉及的对象和步骤,对于一个network IO,我们以read举例,他会涉及到两个系统对象,一个是调用这个IO的process(or thread),另一个就是系统内核。当一个read操作时,该操作会经历两个阶段
# 1.等待数据准备
# 2.将数据从内核拷贝到应用层

# 同步    提交一个任务之后要等待这个任务执行完毕才能继续执行其他的
# 异步 只管提交任务,不用等待该任务执行完毕就可以继续做其他事情
# 阻塞 运行状态 -> 阻塞状态 -> 就绪状态 -> 运行状态、一进程或线程阻塞则会进入阻塞状态休眠
# 非阻塞

  1.非阻塞IO

# 非阻塞IO
# import socket
# sk = socket.socket()
# sk.setblocking(False) # 设置非阻塞
# sk.bind(('127.0.0.1', 8080))
# sk.listen()
#
# try:
# conn, addr = sk.accept() # 因为将套接字设置为了非阻塞,所以这里会报错,因为accept不允许为非阻塞性的,所以下面捕捉异常,有异常则直接pass
# print('有客户端连接上来 ')
# except BlockingIOError:
# pass

  2.阻塞IO

  3.IO多路复用

    # 在windows、linux上,有一个select专门提供IO多路复用的。
# poll机制 # linux上有
# epoll机制 # linux上有
# poll机制和epoll机制使用方法和select一样
# poll可以监听的对象比select可以监听的多。如果select能监听500,则poll能监听1000个类似这样
# poll和select都是操作系统去轮询机制的监听被监听的项,看是否有读操作等,随着监听列表增多,会导致效率变差
# epoll机制
# 给每一个被监听的对象都绑定了一个回调函数,当被监听的对象有监听事件后,会触发此监听对象绑定的回调函数这种机制比select和poll的轮询效率要高,高并发非常有用
# import selectors 这个模块会帮助你选择当前操作系统上最优的IO多路复用

  3.1 IO多路复用中的select

  服务端

import select   # 内置的select模块,用于IO多路复用
import socket
# select.select(rlist, wlist, xlist, timeout=None)
# 参数是3个列表,一个监听超时时间
# rlist参数,表示监听读,直到监听到读或超时返回
# wlist参数,表示监听写,直到监听到写或超时返回
# xlist参数,表示监听条件
# timeout参数,监听超时时间
# 返回值有三个
sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.setblocking(False) # 设置为非阻塞
sk.listen() read_lst = [sk] # 创建一个列表,想要监听谁,则将哪个对象放进来,这里开始先监听socket对象,当有人向这个socket发起连接的时候,select则会监听到返回一个socket
while 1:
# 调用select后操作系统会帮你监听三个监听列表,这里监听的是监听读列表
r_lst, w_lst, x_lst = select.select(read_lst, [], []) # 当监听到后,返回一个元组,元组中有三个元素,分别是rlist,wlist,xlist。这里rlist中最开始监听sk,因此当有客户端连接上来后,会监听有要被读的事件,这里会返回得到一个r_lst,r_lst中有一个sk对象
#print(r_lst)
for i in r_lst:
if i is sk: # 判断监听到的对象是否是sk对象
conn, addr = i.accept() # 此时直接sk.accpet()就会得到客户端连接和地址
read_lst.append(conn) # 将客户端连接符加入到监听列表中
else: # 如果监听到的不是sk对象, 这里的第二可能是监听到了客户端连接符有要被读的事件
msg = i.recv(1024)
if msg == b'': # 当客户端连接关闭时,会接收到空的数据,
i.close() # 因为客户端连接主动关闭,这里也要关闭下这个客户端连接
read_lst.remove(i) # 同时在监听列表中去除这个客户端连接符,不再去监听它
continue
print(msg)

  3.2 linux上更好的IO多路复用epoll、selectors选择当前系统最优的IO多路复用机制

  服务端

# linux上的selectors IO多路复用机制,IO多路复用机制,默认选择系统最优,linux上肯定选择epoll
import selectors
from socket import * def read(conn, mask):
'''
将来要绑定的回调函数
:param conn:
:param mask:
:return:
'''
try:
data = conn.recv(1024)
if not data: # 如果监听客户端的数据是空数据,则表示客户端连接关闭了
print('closeing', conn)
sel.unregister(conn) # 在监听列表中去除这个客户端连接的监听
conn.close() # 同时服务端也关闭这个客户端连接描述符
return
conn.send(data.upper() + b'SB')
except Exception: # 该客户端连接描述符监听到异常事件,则直接关闭客户端连接
print('closing', conn)
sel.unregister(conn) # 在监听列表中去除这个客户端连接的监听
conn.close() # 同时服务端也关闭这个客户端连接描述符 def accept(server_fileobj, mask):
''' :param server_fileobj: 接收到的socket
:param mask:
:return:
'''
conn, addr = server_fileobj.accpet() # 得到客户端连接描述符
sel.register(conn, selectors.EVENT_READ, read) # 将conn客户端连接符注册到监听列表中,监听的是其读时间,绑定的回调函数是read if __name__ == '__main':
sk = socket()
sk.setblocking(SOL_SOCKET, SO_REUSEPORT, 1)
sk.bind(('127.0.0.1', 8080))
sk.listen(5)
sk.setblocking(False)
sel = selectors.DefaultSelector() # 获取到当前操作系统最优的IO多路复用机制
sel.register(sk, selectors.EVENT_READ, accept) # 将socket对象注册到监听列表中,监听其读事件,当有读事件时绑定的回调函数accpet会被执行 # server_fileobj = socket(AF_INET, SOCK_STREAM)
# server_fileobj.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
# server_fileobj.bind(('127.0.0.1', 8080))
# server_fileobj.listen(5)
# server_fileobj.setblocking(False)
# sel.register(server_fileobj, selectors.EVENT_READ, accept) while True:
events = sel.select() # 检测到所有的fileobj(监听列表中的所有对象,都是文件描述符),是否有完成wait data阶段。当监听到有事件时返回
for sel_obj, mask in events:
callback = sel_obj.data # 第一次是callback = accpet 通过sel_obj.data就能拿到刚刚这个被监听对象的回调函数
callback(sel_obj.fileobj, mask) # 第一次是ccpet(server_fileobj, 1) 直接调用回调函数

  客户端

import socket
from threading import Thread def func():
sk = socket.socket()
sk.connect(('127.0.0.1', 8080))
sk.send(b'hello')
sk.close() if __name__ == '__main__':
for i in range(20):
Thread(target=func).start()

  4.信号驱动IO

  5.异步IO

 6.五种IO模型的比较,个人觉得肯定还是异步IO好

说说基于网络的五种IO模型的更多相关文章

  1. 聊聊 Linux 中的五种 IO 模型

    本文转载自: http://mp.weixin.qq.com/s?__biz=MzAxODI5ODMwOA==&mid=2666538919&idx=1&sn=6013c451 ...

  2. Linux 下的五种 IO 模型

    概念说明 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的 ...

  3. [转载] Linux五种IO模型

      转载:http://blog.csdn.net/jay900323/article/details/18141217     Linux五种IO模型性能分析   目录(?)[-] 概念理解 Lin ...

  4. 2018.5.4 Unix的五种IO模型

    阻塞非阻塞和异步同步 同步和异步关注的是消息通信机制,关注两个对象之间的调用关系. 阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态,关注单一程序. Unix的五种IO模型 以下基于Li ...

  5. Windows五种IO模型性能分析和Linux五种IO模型性能分析

    Windows五种IO模型性能分析和Linux五种IO模型性能分析 http://blog.csdn.net/jay900323/article/details/18141217 http://blo ...

  6. (转载) Linux五种IO模型

    转载:http://blog.csdn.net/jay900323/article/details/18141217     Linux五种IO模型及分析   目录(?)[-] 概念理解 Linux下 ...

  7. 五种IO模型

    参考文档 https://www.jianshu.com/p/486b0965c296 概念说明 用户空间和内核空间        现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空 ...

  8. linux的五种IO模型

    概念: 同步.异步.阻塞.非阻塞的概念 同步:所谓同步,发起一个功能调用的时候,在没有得到结果之前,该调用不返回,也就是必须一件事一件事的做,等前一件做完了,才能做下一件. 提交请求->等待服务 ...

  9. Linux 中的五种 IO 模型

    Linux 中的五种 IO 模型 在正式开始讲Linux IO模型前,比如:同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一 ...

随机推荐

  1. CentOS8平台nginx日志的定时切分

    一,编写bash脚本: [root@yjweb crontab]# vi split_nginx_logs.sh 代码: #!/bin/bash # 备份nginx的日志 # 昨天的日期 file_d ...

  2. CentOS7下RabbitMQ服务安装配置 (亲测有效)

    erlang 21.3 rabbitmq-server 3.7.14 下载地址 链接: https://pan.baidu.com/s/1g_T1Q_6zpyO3AepS0ZPgYQ 提取码: abq ...

  3. 【转】Centos7系统下忘记了root管理员账号密码的解决方式

    哎,事情的起因就是脑子背了,曾经还手贱把root密码改了,导致普通账户改不回管理员账号了,然而,这次是百毒"救"了我,最终完美修改了root密码,好文章特地转载过来了,侵权删. 原 ...

  4. 国内npm镜像源设置

    淘宝npm镜像 搜索地址:http://npm.taobao.org/ registry地址:http://registry.npm.taobao.org/ cnpmjs镜像 搜索地址:http:// ...

  5. Redis基础(一)数据结构与数据类型

    Redis数据结构 Redis一共有六种数据结构,分别是简单动态字符串.链表.字典.跳表.整数集合.压缩列表. 简单动态字符串(SDS) Redis只会使用C字符串作为字面量,在大多数情况下,Redi ...

  6. LeakCanary检测内存泄漏

    内存泄漏原因: 线程造成的内存泄漏 Handler造成的内存泄漏 单例导致内存泄露 静态变量导致内存泄露 非静态内部类导致内存泄露 未取消注册(BroadcastReceiver )或回调导致内存泄露 ...

  7. D. Road to Post Office 解析(思維)

    Codeforce 702 D. Road to Post Office 解析(思維) 今天我們來看看CF702D 題目連結 題目 略,請直接看原題. 前言 原本想說會不會也是要列式子解或者二分搜,沒 ...

  8. MYSQL 那些事

    1.一条update语句 1.先通过引擎找到对应的行数据,并加锁 2.对行数据进行修改并调用引擎接口修改这条数据,然后释放锁(此时并没有把数据在磁盘上做出修改) 3.redo log在内存中生成这条u ...

  9. 使用udev高效、动态的管理Linux设备文件

    导读: 在Linux环境中,所有的设备都以文件的形式存在,在早期的Linux版本中,/dev目录包含了了所有可能出现的设备文件,很难想象Linux用户如何从大量的设备文件中找到想要的设备文件.举个例子 ...

  10. java的“同一”与“相等”

    变量:引用(指向地址) + 值(该变量指向值所储存的那一片内存) 两个变量同一 : 判断 是否 这两个变量指向同一片内存. 两个变量相等 : 判断 是否 这两个变量的类型相同,且值相等. 注:常用的& ...