• IO模型


    一、IO模型

    IO模型就是解决IO问题的方式

    IO指的是输入输出,输入输出设备的速度与CPU相比来说是非常慢的,比如recv,input等都是IO操作

    IO操作的最大问题就是会阻塞程序执行

    IO模型要解决的仅仅是网络IO操作

    IO模型分类(5类):

    1、阻塞IO

    socket默认模块就是阻塞的

    问题:同一时间只能服务一个客户端

    解决方法一:多线程(优点:若并发量不高,效率是比较高的,因为每个客户端都有单独线程来处理。弊端:线程需要占用资源,不能无限去开线程)

    解决方法二:多进程(优点:可以多个CPU并行处理。弊端:占用的资源非常大,一旦客户很多,速度就会变慢)

    解决方法三:线程池(优点:保证了服务器正常运行,负责创建和销毁线程以及任务分配。弊端:并发量超出最大线程数量,会造成阻塞)

    解决方法四:协程(优点:不需要创建线程,不需要再线程之间切换,没有数量限制。弊端:不能利用多核优势,单核处理器性能是有上限的,如果并发很大处理器速度就会变慢)

    真正导致效率低的是阻塞问题,以上方法都没有真正的解决阻塞问题,只是避开了阻塞问题

    2、非阻塞IO

    遇到IO操作也不会阻塞,仍然会继续执行。即使遇到IO,CPU执行权也不会剥夺,程序效率会变更高。

    3、IO多路复用*****

    一些程序占用CPU太高,原因是需要无限的循环去向操作系统拿数据

    IO多路复用也是单线程并发处理所有请求

    与非阻塞不同之处是不需要频繁不断地发送系统调用,只要等到select选择准备就绪socket,然后进行处理

    4、异步IO(爬虫阶段)

    5、信号驱动(了解)

    二、IO多路复用

     1 import socket
     2 c = socket.socket()
     3 c.connect(("127.0.0.1,8080))
     4 print("已连接")
     5 
     6 while True:
     7     msg = input(">>>").strip()
     8     if not msg:continue
     9     c.send(msg.encode("utf-8"))
    10 
    11     data = c.recv(1024)
    12     print(data.decode("utf-8"))
    客户端 View Code
     1 import socket
     2 import time
     3 import select
     4 s = socket.socket()
     5 s.bind(("127.0.0.1",8080))
     6 s.listen()
     7 
     8 r_list = [s]
     9 w_list = []
    10 data_dic ={}
    11 while True:
    12     readables,writeables,_ = select.select(r_list,w_list,[])
    13     for i in readables:
    14         if i ==s:
    15             c,_ = i.accept()
    16             r_list.append(c)
    17         else:
    18             try:
    19                 data = i.recv(1024)
    20                 if not data:
    21                     i.close()
    22                     r_list.remove(i)
    23                     continue
    24                 print(data)
    25                 w_list.append(i)
    26                 data_dic[i] =data
    27             except ConnectionResetError:
    28                 i.close()
    29                 r_list.remove(i)
    30     for i in writeables:
    31         try:
    32             i.send(data_dic[i].upper())
    33         except ConnectionResetError:
    34             i.close()
    35         finally:
    36             data_dic.pop(i)
    37             w_list.remove(i)
    服务器 View Code

    三、阻塞IO模型

     1 import socket
     2 import os
     3 c = socket.socket()
     4 c.connect(("127.0.0.1",9999))
     5 print("connect...")
     6 
     7 while True:
     8     msg = "%s 发来问候"% os.getpid()
     9     if not msg:continue
    10     c.send(msg.encode("utf-8"))
    11     data = c.recv(1024)
    12     print(data.decode("utf-8"))
    客户端 View Code
     1 import socket
     2 from threading import Thread
     3 s = socket.socket()
     4 s.bind(("127.0.0.1",9999))
     5 s.listen
     6 
     7 def talking(c):
     8     while True:
     9         try:
    10             data = c.recv(1024)
    11             print("recv...")
    12             if not data:
    13                 c.close()
    14                 break
    15             c.send(data.upper())
    16         except ConnectionResetError:
    17             c.close()
    18             break
    19 while True:
    20     c,addr = s.accept()
    21     print("accept...")
    22     t = Thread(target=talking,args=(c,))
    23     t.start()
    服务器 View Code

    四、非阻塞IO模型

     1 import socket
     2 c = socket.socket()
     3 c.connect(("127.0.0.1",9999))
     4 print("已连接")
     5 
     6 while True:
     7     msg = input(">>>").strip()
     8     if not msg:continue
     9     c.send(msg.encode("utf-8"))
    10     data = c.recv(1024)
    11     print(data.encode("utf-8"))
    客户端 View Code
     1 import socket
     2 s = socket.socket()
     3 s.bind(("127.0.0.1",9999))
     4 s.listen()
     5 s.setblocking(False)
     6 
     7 cs = []
     8 send_cs = []
     9 
    10 while True:
    11     try:
    12         c,addr = s.accept()
    13         print("run accept")
    14         cs.append(c)
    15     except BlockingIOError:
    16         for c in cs[:]:
    17             try:
    18                 data = c.recv(1024)
    19                 if not data:
    20                     c.close()
    21                     cs.remove(c)
    22                 print(data.decode("utf-8"))
    23                 send_cs.append((c,data))
    24             except BlockingIOError:
    25                 continue
    26             except ConnectionResetError:
    27                 c.close()
    28                 cs.remove(c)
    29         for item in send_cs[:]:
    30             c,data = item
    31             try:
    32                 c.send(data.upper())
    33                 send_cs.remove(item)
    34             except BlockingIOError:
    35                 c.close
    36             except ConnectionResetError:
    37                 c.close()
    38                 send_cs.remove(item)
    39                 cs.remove(c)
    服务器 View Code
  • 相关阅读:
    Nginx负载均衡
    MySQL主从复制
    笔记
    tomcat工作原理
    Nginx工作原理
    Loj#6183. 看无可看
    [BZOJ 2759] 一个动态树好题
    5255 -- 【FJOI2016】神秘数
    [NOI2015]寿司晚宴
    [CQOI2017]老C的键盘
  • 原文地址:https://www.cnblogs.com/zhangzhechun/p/10518872.html
Copyright © 2020-2023  润新知