博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python_阻塞IO、非阻塞IO、IO多路复用
阅读量:4507 次
发布时间:2019-06-08

本文共 4003 字,大约阅读时间需要 13 分钟。

0、承上

   进程:

    计算机里最小的资源分配单位;

    数据隔离, 利用多核,数据不安全。

 

  线程:

    计算机中最小的CPU调度单位;

    数据共享,GIL锁,数据不安全.

 

  协程:

    线程的一部分,是有用户来调度的;

    数据共享,数据安全.

 

  异步:  同时做不止一件事情.

 

  同步:  事情一件接着一件 的做.

 

  阻塞:  recv、recvfrom、accept、sleep、input

 

  非阻塞:平时遇见的处过上边基本上都是。

 

  IO操作:

    网络相关的操作

    文件处理、json.dump/load、logging、print、input、recv/send、connect/accept、recvfrom/sendto

 

  recv为什么要阻塞?

    等待数据到来到Python程序的内存中。

 

 

  IO模型一共有五种,由于信号驱动IO不常用,我们这里主要介绍阻塞IO、非阻塞IO、IO多路复用以及异步IO。

  对于一个network IO(这里以read举例),它会涉及到两个系统对象,一个是调用这个IO的process(or thread),另一个就是系统内核(kernel).当一个read操作发生时,该操作会经历两个阶段:

    (1)  等待数据准备( Waiting for the data to be ready )

    (2)  将数据从内核拷贝到进程中( Copying the data from the kernel to the process )

  这些IO模型的区别就在这两个阶段上各有不同.

 

1、阻塞IO( Blocking IO )

   在Linux中,默认情况下所有的socket都是blocking读操作流程大概如下:

 

1 import socket 2  3 sk = socket.socket() 4 sk.setblocking(True) 5  6 # True  阻塞 7 # False  非阻塞 8 # TCP协议的socket sever不能同时接收多个请求 9 # sk.accept()10 # while True:11 #     conn.recv()

 

  

2、非阻塞IO(non-blocking IO)

  非阻塞的形式实现了并发的socket server.

  非阻塞的形式实现了并发的socket sever,太耗CPU.

  没有数据来的时候程序的高速处理极大地占用了CPU资源.

 

 

 

 

1 import socket 2  3 sk = socket.socket() 4 sk.bind(('127.0.0.1', 9000)) 5 sk.setblocking(False) 6 sk.listen() 7 conn_lst = [] 8 del_lst = [] 9 while True:10     try:11         conn,addr = sk.accept() # 非阻塞,没有连接来就报错12         conn_lst.append(conn)13         print(conn)14     except BlockingIOError:15         for con in conn_lst:16             try:17                 con.send(b'hello')18                 try:19                     print(con.recv(1024))   # 非阻塞 没有消息来就报错20                 except BlockingIOError: # 没有消息就报错21                     pass22             except ConnectionResetError:    # send没有连接的报错23                 con.close()24                 del_lst.append(con)25         for con in del_lst:26             conn_lst.remove(con)27         del_lst.clear()
服务器端
1 import socket2 3 sk = socket.socket()4 sk.connect(('127.0.0.1', 9000))5 while True:6     print(sk.recv(1024))7     sk.send(b'bye')8 sk.close()
客户端

 

  sever:

 

 

 结果:

D:\Python36\python.exe E:/Python/草稿纸0.py
b'bye'b'byebye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'bye'b'byebye'b'bye'b'bye'b'bye'b'byebye'b'bye'b'bye'b'bye'b'bye'Process finished with exit code 1
服务器端
D:\Python36\python.exe E:/Python/草稿纸.pyb'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hello'b'hellohellohello'b'hello'b'hello'b'hellohellohello'b'hello'b'hello'b'hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello'b'hellohello'b'hello'
客户端结果

 

   由于通信的一直是小数据块(大小不够1024),出现了黏包现象. 

 

3、IO多路复用(IO multiplexing)

 

 

 

 

1 import select 2 import socket 3  4 sk = socket.socket() 5 sk.bind(('127.0.0.1', 9000)) 6 sk.setblocking(False) 7 sk.listen() 8  9 rlst = [sk] # 监听的是对象的读操作10 wlst = []   # 监听的是对象的写操作11 xlst = []   # 监听的是对象的异常操作12 while True:13     rl,wl,xl = select.select(rlst, wlst, xlst)14     for obj in rl:15         if obj == sk:16             conn,addr = sk.accept()17             rlst.append(conn)18         else:19             msg = obj.recv(1024)20             if msg == b'':21                 obj.close()22                 rlst.remove(obj)23                 continue24             print(msg)25             obj.send(b'hello')
IO多路复用-sever端
1 import socket2 3 sk = socket.socket()4 sk.connect(('127.0.0.1', 9000))5 while True:6     sk.send(b'wahaha')7     print(sk.recv(1024))8 sk.close()
IO多路复用-client端

 

 

  socketsever —— TCP协议的并发操作  selectors + 多线程

  IO多路复用的select的工作机制

    select  Windows  轮询

    poll      Linux        轮询,poll能够监听的对象比select要多

    epoll    Linux        不是采用轮询的方式,而是采用回调函数的形式

 

 

转载于:https://www.cnblogs.com/ZN-225/p/9203674.html

你可能感兴趣的文章
<转>OD常用断点列表
查看>>
描边时消除锯齿SetSmoothingMode
查看>>
15回文相关问题
查看>>
将VS2013项目转成VS2010项目的方法
查看>>
[置顶] 怎么对待重复的代码
查看>>
多种方法实现H5网页图片动画效果;
查看>>
Ubuntu/CentOS下使用脚本自动安装 Docker
查看>>
源码解读Mybatis List列表In查询实现的注意事项
查看>>
POJ 2311 Cutting Game(二维SG+Multi-Nim)
查看>>
1978 Fibonacci数列 3
查看>>
1225 八数码难题
查看>>
C#控件的闪烁问题解决方法总结
查看>>
js 冒泡事件与解决冒泡事件
查看>>
2018-2019赛季多校联合新生训练赛第七场(2018/12/16)补题题解
查看>>
后台全选功能以及数据的提交方法
查看>>
Android 动画效果 及 自定义动画
查看>>
const与#define相比有什么不同?
查看>>
Eclipse4.7 SpringIDE插件的安装
查看>>
C#面向对象基础
查看>>
adb server is out of date. killing...
查看>>