Python Select模型
IO多路复用
IO多路复用就是我们经常说的select epoll.select和epoll的好处是单个process就可以同时处理多个网络IO。基本原理是select\epoll会不断的轮询所负责的所有socket,当有某个socket数据到达了,就通知用户进程。
下面是流程图:

当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。
注意1:select函数返回结果中如果有文件可读了,那么进程就可以通过调用accept()或recv()来让kernel将位于内核中准备到的数据copy到用户区。
注意2: select的优势在于可以处理多个连接,不适用于单个连接
selectors
基于select模块实现的IO多路复用
`
IO多路复用实现机制
在不同的平台上是不一样的,win平台只有select,Linux平台有select poll epoll
win: select
linux : select poll epoll
通常是用户空间创建fd,然后copy到内核空间
如果是开fd的数量多,select的的效率低
基于select模块实现的IO多路复用
import selectors
import socket
sock = socket.socket()
sock.bind(("127.0.0.1", 8810))
sock.listen(5) # 这里虽然设置了最大连接数,但是已经没有限制了
sel = selectors.DefaultSelector() # 实例化一个对象,会根据不同的平台自动设置优先级
# epoll|kqueue|devpoll > poll > select. 所以Linux系统会自动设置成epoll win 自动设置成select
# 第二步
def read(conn, mask):
# pass
try: # win 检测异常 当有异常 如客户端断开的时候
data = conn.recv(1024)
print(data)
print(data.decode("utf-8"))
data2 = input(">>>")
conn.send(data2.encode("utf-8"))
except Exception:
sel.unregister(conn) # 解除注册
# 第一步
def accept(sock, mask): # mask 是没有用的
conn, addr = sock.accept()
# print(conn)
sel.register(conn, selectors.EVENT_READ, read) # 把conn 添加到列表中
# 首先要注册 只是把sock和 accept绑定
sel.register(sock, selectors.EVENT_READ, accept) # 注册,但是没有监听accept函数
# 监听
while 1:
print("waiting...")
# event 就是那个r
events = sel.select() # [(key,mask) ,(key,mask) ,(key,mask) ,)] # 活活动的对象会自动添加到这里
for key, mask in events: # events 是个列表 需要遍历
print(key.data) # 拿到accept函数
print(key.fileobj) # 当前的活动的对象 sock 文件句柄
func = key.data # 调用
obj = key.fileobj #
func(obj, mask) # 第一个参数是sock 对象
# break
select缺点:
- 每次调用slect都要将所有的fd拷贝到内核空间(每次都要拷贝),导致效率下降
- 监听的的实现是通过遍历所有的fd,(遍历消耗的时间消耗多)判断是否有数据访问
- 最大连接数(input中放的文件描述符数量1024)
poll:
最大连接数没有限制了,除此之外,和select一样,所以基本不用
epoll:
内部通过3个函数实现(select是一个)
第一个函数:
创建epoll句柄,把所有的fd拷贝到内核空间,只需要拷贝一次第二个函数: 回掉函数
某一个函数或者动作成功完成后,会自动触发一个函数
为所有的fd绑定一个回调函数,一旦有数据访问,触发改回调函数,回调函数把fd放到链表中。(只要有活动,把fd放到链表中,动态监听)这样就提高了效率
例子:交试卷第三个函数,判断链表是否为空
selectors.DefaultSelector()
selectors会根据自己的平台选择最佳IO多路复用,自动选择。win只有select
linux的中epoll中的优先级最高
队列queue
和线程有关系的,在多线程的时候有用,保证信息安全的
队列是一种数据类型
优点:
保证线程安全,不用自己加锁
put get
先进先出
import queue
q = queue.Queue(3) # 默认是先进先出 FIFO 设置参数是最大的存放数量5
q.put(111)
q.put("hello")
q.put(222)
q.put(333,False) # 默认blocking = True ,False 是当存满的时候,自动报错,解除阻塞的状态
print(q.get())
print(q.get())
print(q.get())
print(q.get()) # 第4次已经拿不到了 取不到 默认阻塞
q.get(False) # 解除阻塞状态
先进后出
q = queue.LifoQueue()
q.put(111)
q.put(222)
print(q.get())
print(q.get())
优先级
q = queue.PriorityQueue()
q.put([4,"hello4"])
q.put([1,"hello1"])
q.put([2,"hello2"])
print(q.get())
print(q.get())
print(q.get())
join 与task_done方法
import queue
q = queue.Queue(5)
q.put(111)
q.put(222)
q.get()
q.task_done() #
q.get()
q.task_done() #
q.join() # 等待task_done 和events是一个原理
print('endnig')
join 与task_done方法必须配合使用
其他的用法
q.qsize() 返回队列的大小
q.empty() 如果队列为空,返回True,反之False
q.full() 如果队列满了,返回True,反之False
q.full 与 maxsize 大小对应
q.get([block[, timeout]]) 获取队列,timeout等待时间
q.get_nowait() 相当q.get(False)非阻塞
q.put(item) 写入队列,timeout等待时间
q.put_nowait(item) 相当q.put(item, False)
q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号
q.join() 实际上意味着等到队列为空,再执行别的操作
生产者消费者模型
有生产数据的线程
有消费数据的线程
通过一个容器来解决生产者消费者强耦合的问题
这个容器是用来解耦的(类似吃饭的时候的服务员)
目录结构也是一种解耦
下面是用队列模拟实现
import time,random
import queue,threading
q = queue.Queue()
def Producer(name):
count = 0
while count <10:
print("making........")
time.sleep(random.randrange(3))
q.put(count)
print('Producer %s has produced %s baozi..' %(name, count))
count +=1
#q.task_done()
#q.join()
print("ok......")
def Consumer(name):
count = 0
while count <10:
time.sleep(random.randrange(4))
if not q.empty():
data = q.get()
#q.task_done()
#q.join()
print(data)
print('\033[32;1mConsumer %s has eat %s baozi...\033[0m' %(name, data))
else:
print("-----no baozi anymore----")
count +=1
p1 = threading.Thread(target=Producer, args=('A',))
c1 = threading.Thread(target=Consumer, args=('B',))
# c2 = threading.Thread(target=Consumer, args=('C',))
# c3 = threading.Thread(target=Consumer, args=('D',))
p1.start()
c1.start()
# c2.start()
# c3.start()
Python Select模型的更多相关文章
- Python Select模型(程序流程)(转)
缘由 之前写socket的CS模型代码,都是利用最原始的多线程方式.服务端是主线程,接到客户端的连接请求就从线程池中获取一个线程去处理整个socket连接的所有操作,虽然在连接数较短的情况下没有什么影 ...
- python select模块详解
要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值.select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接 ...
- python select.select模块通信全过程详解
要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值.select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接 ...
- python select模块
Python select 一.前言 Python的select()方法直接调用操作系统的IO接口,它监控sockets,open files, and pipes(所有带fileno()方法的文件句 ...
- 关于 Poco::TCPServer框架 (windows 下使用的是 select模型) 学习笔记.
说明 为何要写这篇文章 ,之前看过阿二的梦想船的<Poco::TCPServer框架解析> http://www.cppblog.com/richbirdandy/archive/2010 ...
- windows socket编程select模型使用
int select( int nfds, //忽略 fd_ser* readfds, //指向一个套接字集合,用来检测其可读性 ...
- socket编程的select模型
在掌握了socket相关的一些函数后,套接字编程还是比较简单的,日常工作中碰到很多的问题就是客户端/服务器模型中,如何让服务端在同一时间高效的处理多个客户端的连接,我们的处理办法可能会是在服务端不停的 ...
- Python Select 解析
首先列一下,sellect.poll.epoll三者的区别 select select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监视多个文件描述符的数组,当select ...
- linux下多路复用模型之Select模型
Linux关于并发网络分为Apache模型(Process per Connection (进程连接) ) 和TPC , 还有select模型,以及poll模型(一般是Epoll模型) Select模 ...
随机推荐
- 有关Linux的.a、.so和.o文件---mark一下(转)
gcc 生成 .a静态库和 .so动态库 (转载) 我们通常把一些公用函数制作成函数库,供其它程序使用.函数库分为静态库和动态库两种.静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该 ...
- SpringMVC中的常用注解
RequestParam 作用: 用于 将请求参数区数据 映射到 功能处理方法的参数上. 属性: value 请求参数中的名称 required 请求参数中是否必须提供此参数. 默认值: ...
- 用js判断屏幕的宽度,改变html字体大小用rem布局
if (document.documentElement.clientWidth > 600) {//页面宽度大于600px让其宽度等于600px,字体大小等于60px,居中 document. ...
- poj 2049(二分+spfa判负环)
poj 2049(二分+spfa判负环) 给你一堆字符串,若字符串x的后两个字符和y的前两个字符相连,那么x可向y连边.问字符串环的平均最小值是多少.1 ≤ n ≤ 100000,有多组数据. 首先根 ...
- 剑指Offer的学习笔记(C#篇)-- 平衡二叉树(二叉树后序遍历递归详解版)
题目描述 输入一棵二叉树,判断该二叉树是否是平衡二叉树. 一 . 题目分析 首先要理解一个概念:什么是平衡二叉树,如果某二叉树中任意的左右子树深度相差不超过1,那么他就是一颗平衡二叉树.如下图: 所以 ...
- BitMap的原理以及运用
位图(Bitmap),即位(Bit)的集合,是一种数据结构,可用于记录大量的0-1状态,在很多地方都会用到,比如Linux内核(如inode,磁盘块).Bloom Filter算法等,其优势是可以在一 ...
- 关于表格——增加删除行,鼠标选定(利用JavaScript)
涉及到的知识点: 1.onmouseover,onmouseout 2.dom getElementByTagName 3.新建节点元素createElement; <!DOCTYPE html ...
- CODING 告诉你硅谷的研发项目管理之道(5)
CODING 已经通过前四期文章,让大家逐步了解了一些硅谷优秀的项目管理者是如何工作.如何维持团队高效运作的.在过去的十几年中,中国的互联网行业发展过于迅猛,导致很多管理人员都是赶鸭子上架,商场如战场 ...
- katalon studio配置git与git项目创建
katalon 是一款在2015年诞生的可以安装在windows.macOS.linux操作系统上,基于selenium 和 Appium 测试框架,并集成了这些框架的优点的自动化测试工具.关于这个工 ...
- A-坐飞机
链接:https://ac.nowcoder.com/acm/contest/892/A 题意: 鸡尾酒要去很多很多地方玩,于是他一次买了 n 张机票,初始鸡尾酒在第一个城市,对于任意的i(1≤i≤n ...