python实例解释五种IO模型(1)--------阻塞式IO
我们都知道,unix下可用的IO模型有五种,分别是
- 阻塞式IO
- 非阻塞式IO
- I/O复用(select和epoll)
- 信号驱动式I/O
- 异步IO
下面通过一个个实例来解释各种IO之间的区别
1.阻塞式IO
阻塞式IO是最常见的一种IO模型,默认情况下所有的套接字都是阻塞的。阻塞式IO可以用下面这张图来描述
应用程序调用一个系统调用向内核请求数据,此时如果数据没有准备好,那么进程在此阻塞,切换至内核态运行,内核去准备数据。内核准备好数据后,并复制到应用进程的内核缓冲区或者发生错误才会返回。这里最常见的错误就是系统调用被信号中断。系统调用返回之后,应用进程开始处理数据。
2.例子
在这里我们写一个小例子,这个小例子实现客户端向服务端发送数据。服务端收到数据后,会打印到控制台。如果客户端发送88,那么关闭连接,程序退出。代码如下:
服务端程序:
import socket # 导入 socket 模块
import time
s = socket.socket() # 创建 socket 对象
host = socket.gethostname() # 获取本地主机名
port = 12345 # 设置端口
s.bind((host, port)) # 绑定端口
s.listen(5) # 等待客户端连接
c, addr = s.accept() # 建立客户端连接。
# c.setblocking(True)
print("connected from :%s:%s"%(addr[0],addr[1]))
while True:
print("wating for client input")
data = c.recv(1024)
data = str(data,'utf-8')
print(data)
if data == '88':
c.close()
break
print("client closed connection")
s.close()
客户端程序:
import socket # 导入 socket 模块
s = socket.socket() # 创建 socket 对象
host = socket.gethostname() # 获取本地主机名
port = 12345 # 设置端口号
s.connect((host, port))
print("connected to server")
while(True):
data = input()
s.send(bytes(data,'utf-8'))
if data == '88':
s.close()
break
看一下程序运行效果
首先,启动服务端程序后,发现服务端没有任何输出,此时程序阻塞在第8行,等待客户端连接。
`
然后我们启动客户端程序
发现服务器端打印出
connected from :192.168.1.174:7454
wating for client input
客户端打印出
connected to server
此时,服务器端阻塞在13行,等待客户端发送数据。
在客户端发送一条消息
服务器端打印出客户端发送过来的数据,打印出来,然后再次在第13行阻塞,继续等待客户端发送数据
客户端发送88后,程序打印出结束信息,然后结束运行。
上面就是阻塞式IO的运行效果,这种IO是最简单也是最流行的一种IO。