Python入门day42——io模型

一:IO模型简洁

* blocking IO           阻塞IO
* nonblocking IO      非阻塞IO
* IO multiplexing      IO多路复用
* asynchronous IO    异步IO
	由于 signal driven IO(信号驱动IO)不常用,所以主要介绍其余4种
1.等待数据准备(Waiting for the data to be ready)
2.将数据从内核拷贝到进程中(Copying the data from the kernel to the process)

001

同步异步
阻塞非阻塞
常见的网络阻塞状态:
	accept
	recv
	recvfrom
	
	send虽然它也有IO行为 但是不在我们的考虑范围

二:阻塞IO

005

我们之前写的都是阻塞IO模型	协程除外
import socket

server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)

while True:
    conn, addr = server.accept()
    while True:
        try:
            data = conn.recv(1024)
            if len(data) == 0:
                break
            print(data)
            conn.send(data.upper())

        except ConnectionResetError as e:
            print(e)
    conn.close()
    
# 在服务端开设多进程或者多线程,进程池线程池,其实还是没有解决IO问题
该等的地方还是得等 没有规避
只不过多个人等待的时候 彼此互不干扰

三:非阻塞IO

003

服务端:

import socket
import time


server = socket.socket()
server.bind(('127.0.0.1', 8081))
server.listen(5)
server.setblocking(False)
# 将所有的网络阻塞变为非阻塞
r_list = []
del_list = []
while True:
    try:
        conn, addr = server.accept()
        r_list.append(conn)
    except BlockingIOError:
        # time.sleep(0.1)
        # print('列表的长度:',len(r_list))
        # print('做其他事')
        for conn in r_list:
            try:
                data = conn.recv(1024)  # 没有消息 报错
                if len(data) == 0:  # 客户端断开链接
                    conn.close()  # 关闭conn
                    # 将无用的conn从r_list删除
                    del_list.append(conn)
                    continue
                conn.send(data.upper())
            except BlockingIOError:
                continue
            except ConnectionResetError:
                conn.close()
                del_list.append(conn)
        # 挥手无用的链接
        for conn in del_list:
            r_list.remove(conn)
        del_list.clear()

客户端:

import socket


client = socket.socket()
client.connect(('127.0.0.1',8081))


while True:
    client.send(b'hello world')
    data = client.recv(1024)
    print(data)

总结:

虽然非阻塞IO给你的感觉非常牛逼
但是该模型会 长时间占着CPU不用  让CPU不停的空转 占着茅坑不拉屎
我们实际应用中也不会考虑使用非阻塞IO模型

任何的技术点都有它存在的意义 
实际应用或者是思想借鉴

四:IO多路复用

002

当监管的对象只有一个的时候 其实IO多路复用连阻塞IO都比比不上!!!
但是IO多路复用可以一次性监管很多个对象

server = socket.socket()
conn,addr = server.accept()

监管机制是操作系统本身就有的 如果你想要用该监管机制(select)
需要你导入对应的select模块

服务端:

import socket
import select


server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)
server.setblocking(False)
read_list = [server]


while True:
    r_list, w_list, x_list = select.select(read_list, [], [])
    """
    帮你监管
    一旦有人来了 立刻给你返回对应的监管对象
    """
    # print(res)  # ([<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080)>], [], [])
    # print(server)
    # print(r_list)
    for i in r_list:  #
        """针对不同的对象做不同的处理"""
        if i is server:
            conn, addr = i.accept()
            # 也应该添加到监管的队列中
            read_list.append(conn)
        else:
            res = i.recv(1024)
            if len(res) == 0:
                i.close()
                # 将无效的监管对象 移除
                read_list.remove(i)
                continue
            print(res)
            i.send(b'heiheiheiheihei')

客户端:

import socket


client = socket.socket()
client.connect(('127.0.0.1',8080))


while True:

    client.send(b'hello world')
    data = client.recv(1024)
    print(data)

总结:

监管机制其实有很多
select机制  windows linux都有

poll机制    只在linux有   poll和select都可以监管多个对象 但是poll监管的数量更多

上述select和poll机制其实都不是很完美 当监管的对象特别多的时候
可能会出现 极其大的延时响应

epoll机制   只在linux有
   它给每一个监管对象都绑定一个回调机制
   一旦有响应 回调机制立刻发起提醒

针对不同的操作系统还需要考虑不同检测机制 书写代码太多繁琐
有一个人能够根据你跑的平台的不同自动帮你选择对应的监管机制
selectors模块

五:异步IO

004

异步IO模型是所有模型中效率最高的 也是使用最广泛的
相关的模块和框架
   模块:asyncio模块
   异步框架:sanic tronado twisted
      速度快!!!
import threading
import asyncio


@asyncio.coroutine
def hello():
    print('hello world %s'%threading.current_thread())
    yield from asyncio.sleep(1)  # 换成真正的IO操作
    print('hello world %s' % threading.current_thread())


loop = asyncio.get_event_loop()
tasks = [hello(),hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

六:四个IO模型对比

005

003

002

004

七:总结

网络并发知识点梳理:

1.软件开发架构	B/S;C/S

2.互联网协议
    OSI七层协议
    五层
    每一层都是干嘛的
        以太网协议	广播风暴
        IP协议

        TCP/UDP

3.三次握手、四次挥手

4.Socket简洁

5.TCP粘包问题	定制固定长度的包头

6.UDP协议

7.SocketServer模块

并发编程

1.操作系统发展史

2.多道技术

3.进程理论

4.开启进程的2种方式

5.互斥锁

6.生产者消费者模型

7.线程理论

8.开启线程的2种方式

9.GIL全局解释器锁

10.进程池 线程池

11.协程的概念

12.IO模型
原文地址:https://www.cnblogs.com/yding/p/12797439.html