IO input output
在内存中存在数据交换的操作可以任务是IO操作(输入输出)
e.g.
内存和磁盘进行数据交换:文件的读写,数据库更新
内存和终端数据交换:input ; print ; sys.stdin;sys.stdout;sys.stderr
内存和网络数据的交换:网络链接 recv;send;recvfrom
IO密集型程序:程序中执行中由大量的IO操作,而较少的cpu运算操作;消耗cpu较少,IO运行时间长
CPU(计算)密集型程序:程序中存在大量的cpu运算,IO操作较少,消耗cpu大
IO分类
- 阻塞IO:
程序运行中遇到IO条件没有达成或者传输过程较慢的情况会出现阻塞状态;IO最简单的逻辑情形,也是默认状态。---->效率低的IO形态
阻塞情况:
×因为某种IO条件没有达到形成阻塞:e.g.、accept、recv、recvfrom、input
×处理IO事件的时候耗时较长形成阻塞:e.g.、文件读写过程,网络数据发送过程
- 非阻塞IO:在程序运行中遇到IO的情形不让其产生阻塞
×实现手段:改变IO事件的属性,让其变为非阻塞
×通常会和循环一起使用,进行条件的循环监控
s.setblocking(False)
功能:将套接字设置为非堵塞
参数:默认为堵塞状态,设置为False则为非阻塞
超时检测:将原本阻塞的函数,设置一个阻塞的最长时间,在时间内如果仍然阻塞则不再等待
s.settimeout(sec)
功能:设置套接字的超时时间
参数:时间(秒)
- IO多路复用:
×定义:通过一个监测,可以同时监控多个IO事件的行为,当那个IO事件可以执行,即让这个IO事件发生
×IO事件就绪:IO事件即将发生的一个临界状态
1.在程序中存在的IO事件中选择要检测的
2.创建检测,将检测的IO时间注册
3.等待检测的IO事件发生,判断是什么IO事件
4.处理响应的IO
import select
select -->windows\linux\unix
poll -->linux\unix
epoll -->linux\unix
rs,ws,xs = select(rlist,wlist,xlist[,timeout])
功能:监控IO事件,阻塞等待监控的IO时间发生
参数:
- rlist 列表:存放我们需要等待处理的IO
- wlist 列表:存放我们想主动处理的IO
- xlist 列表:存放出错希望去处理的IO
- timeout 超时检测
返回值: - rs:rlist中准备就绪的IO
- ws:wlist中准备就绪的IO
- xs:xlist中准备就绪的IO
from socket import *
from select import select
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(("192.168.0.106",8888))
s.listen(1024)
rlist = [s]
wlist = []
xlist = [s]
while True:
print("等待IO发生")
rs,ws,xs = select(rlist,wlist,xlist)
for r in rs:
if r is s:
connfd,addr = rs[0].accept()
print("Connet from ",addr)
rlist.append(connfd)
#表示客户端连接套接字准备就绪
else:
data = r.recv(1024)
if not data:
#从关注列表移除
rlist.remove(r)
r.close()
else:
print("Recevie:",data.decode())
#将套接字放入wlist
wlist.append(r)
#ie your message!")
for w in ws:
w.send("这是一条回复消息".encode())
wlist.remove(w)
for x in xs:
if x is s:
s.close()
#poll
from socket import *
from select import *
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(("192.168.0.106",8888))
s.listen(1024)
#创建poll对象
p = poll()
#创建地图
fdmap = {s.fileno():s}
#添加关注
p.register(s,POLLIN|POLLERR)
while True:
#进行IO监控
#[(fileno,event),(),...]
events = p.poll()
for fd,event in events:
if fd == s.fileno():
#从地图中找到fd对应的对象
c,addr = fdmap[fd].accept()
#注册新的IO维护地图
p.register(c,POLLIN)
fdmap[c.fileno()] = c
else:
data = fdmap[fd].recv(1024)
if not data:
p.unregister(fd) #从
fdmap[fd].close()
del fdmap[fd] #从地图删除
else:
print(data.decode())
fdmap[fd].send('收到了'.encode())
#epoll
from socket import *
from select import *
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(("192.168.0.106",8888))
s.listen(1024)
#创建epoll对象
p = epoll()
#创建地图
fdmap = {s.fileno():s}
#添加关注
p.register(s,EPOLLIN|EPOLLERR)
while True:
#进行IO监控
#[(fileno,event),(),...]
events = p.poll()
for fd,event in events:
if fd == s.fileno():
#从地图中找到fd对应的对象
c,addr = fdmap[fd].accept()
#注册新的IO维护地图
p.register(c,EPOLLIN)
fdmap[c.fileno()] = c
else:
data = fdmap[fd].recv(1024)
if not data:
p.unregister(fd) #从
fdmap[fd].close()
del fdmap[fd] #从地图删除
else:
print(data.decode())
fdmap[fd].send('收到了'.encode())
区别:
epoll 效率要高于select和poll
epoll 的触发机制要多—>EPOLLET(边缘触发)
- 事件驱动IO
- 异步IO
本地套接字
cookie
linux下文件类型
b(块设备文件) c(字符设备文件)
d(目录) -(普通文件) l(链接文件)
s(套接字文件) p(管道文件)
作用:用于本地不同程序之间进行数据传输
本地套接字创建流程
1.创建套接字对象
sockfd = socket(AF_UNIX,SOCK_STREAM)
2.绑定套接字文件,如果文件不存在则自动创建
sockfd.bind(file)
3.监听
listen
4.消息收发
recv、send
os.path.exists(file)
功能:判断一个文件是否存在
参数:文件
返回值:存在True 不存在 False
os.remove()
os.unlink()
功能:删除一个文件
参数:要删除的文件
网络基础总结
理论
- 1.OSI七层模型, tcp/ip模型
- 2.tcp 和UDP的区别特征
- 3.三次握手和四次挥手的过程
- 4.什么是IO多路复用,IO的基本形态
- 5.套接字的种类,套接字的类型区别
程序实践:
1.TCP套接字传输的基本模型
2.UDP套接字传输的基本类型
3.IO多路复用select、poll的使用
4.http协议基本原理的实现