响应格式
响应行: 反馈基本的响应情况
格式 :HTTP1.1 200 OK
版本 响应码 附加信息
响应码: 1xx 提示信息, 表示请求被接收
2xx 响应成功
3xx 表示响应需要进一步操作, 重定向
4xx 客户端错误
5xx 服务器错误
常见: 200 成功
401 没有访问权限
404 访问内容不存在
500 服务器异常
响应头: 响应内容的描述
- Cache-Control: private
- Connection: Keep-Alive
- Content-Encoding: gzip
- Content-Type: text/html;charset=utf-8
空行
响应体: 具体的响应内容
* splitlines() 将 bytes 格式字符串按行切割
IO input output
在内存中存在数据交互的操作认为是 IO 操作
和终端交互: input print
和磁盘交互: read write
和网络交互: recv send
IO 密集型程序: 在程序执行中有大量的 IO 操作, 而 CPU 运算较少, 消耗 CPU 资源少, 耗时长
计算密集型程序: 程序中计算较多, IO 操作较少. CPU 消耗较多, 运算速度快
(CPU 密集型)
IO 的类型
阻塞 IO 非阻塞 IO IO 多路复用
阻塞 IO:
阻塞 IO 是 IO 的默认形态, 是效率较低的一种 IO 情形
阻塞情况:
* 因为某种条件没有达成造成的函数阻塞
- for example :
- accept input recv
* 处理 IO 的事件较长产生的阻塞行为
for example:
网络传输, 大文件的读写
非阻塞 IO
* 将原本的阻塞函数通过属性的修改使其变为非阻塞
sockfd.setblocking(bool)
功能: 将套接字设置为非阻塞 IO
参数: 默认为 True 表示套接字调用阻塞函数时为阻塞状态
设置为 False 表示调用阻塞函数变为非阻塞状态
注意: 非阻塞通常和循环一起使用, 不断执行任务, 然后在检测 IO 行为是否满足运行条件
* 超时检测 即设置一个最长阻塞等待时间, 超过时间后则不再阻塞
sockfd.settimeout(sec)
功能: 设置套接字的超时事件
参数: 设置的时间 多少秒
注意: 设置超时检测一定是在阻塞状态下
- cookie
- from time import ctime
ctime() 获取当前时间
IO 多路复用
准备就绪的 IO:IO 能够操作, 可以进行处理执行
定义: 同时监控多个 IO 事件, 当哪个 IO 事件准备就绪就执行哪个 IO 事件.
以此形成可以同时操作多个 IO 的行为, 避免一个 IO 阻塞造成其他的都无法运行, 提高了执行效率
具体方案:
- select: Windows Linux unix
- poll :Linux unix
- epoll :Linux unix
python 模块 select 提供以上三种方法
import select
select 方法: 实现多路复用
rlist,wlist,xlist=select(rlist,wlist,xlist[,timeout])
功能: 监控 IO 事件, 阻塞等待 IO 发生
参数: rlist 列表 想要关注的等待发生的 IO 事件
wlist 列表 想要关注的可以主动处理的 IO
xlist 列表 想要关注的出现异常去处理的 IO
timeout 超时事件, 默认为阻塞设置超时后即阻塞一定的时间
超时结束后, 结束阻塞, 进行下一步
返回值 rlist 列表 rlist 中准备就绪的 IO 对象
wlist 列表 wlist 中准备就绪的 IO 对象
xlist 列表 xlist 中准备就绪的 IO 对象
基于 select IO 多路复用的 TCP 服务端
步骤: 1. 将关注的 IO 放入对应类别的关注列表
2. 通过 select 函数进行监控
3. 遍历 select 返回值确定哪个 IO 事件发生
4. 处理发生的 IO 事件
注意: wlist 中如果存在 IO 事件, select 会立即返回让你处理
在处理 IO 过程中不要出现死循环等长期占有服务端的情况
IO 多路复用占用计算机资源较少, 效率较高
位运算
& 按位与
| 按位或
^ 按位异或
<< 左移
>> 右移
11 1011
14 1110
11&14 1010 10 一 0 则 0
11|14 1111 15 一 1 则 1
11^14 0101 5 相同为 0 不同为 1
11<<2 101100 向左移动, 右侧补零
14>>2 11 3 向右移动, 挤掉低位
- from socket import *
- import select
- s = socket()
- s.bind(('0.0.0.0',2505))
- s.listen(3)
- # 关注套接字 IO
- print("监控 IO")
- rs,ws,xs = select.select([s],[],[],3)
- print("处理 IO")
- from select import select
- from socket import *
- # 创建套接字作为关注的 IO
- s = socket()
- s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
- s.bind(('0.0.0.0',2505))
- s.listen(5)
- # 添加到关注列表
- rlist = [s]
- wlist = []
- xlist = [s]
- while True:
- # 通过 select 进行 IO 监控
- rs,ws,xs = select(rlist,wlist,xlist)
- for r in rs:
- # 如果 r is s 说明 s 就绪既有客户端发起链接
- if r is s:
- c,addr = r.accept()
- print("Connect from",addr)
- rlist.append(c)
- # 某个客户端链接套接字就绪
- else:
- data = r.recv(1024)
- if not data:
- rlist.remove(r)
- r.close()
- continue
- print("收到消息:",data.decode())
- # r.send("收到消息".encode())
- wlist.append(r)
- for w in ws:
- w.send("收到消息".encode())
- wlist.remove(w)
- for x in xs:
- x.close()
- raise
- from select import select
- from socket import *
- # 创建套接字作为关注的 IO
- s = socket()
- s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
- s.bind(('0.0.0.0',2505))
- s.listen(5)
- # 添加到关注列表
- rlist = [s]
- wlist = []
- xlist = [s]
- while True:
- # 通过 select 进行 IO 监控
- rs,ws,xs = select(rlist,wlist,xlist)
- for r in rs:
- # 如果 r is s 说明 s 就绪既有客户端发起链接
- if r is s:
- c,addr = r.accept()
- print("Connect from",addr)
- rlist.append(c)
- # 某个客户端链接套接字就绪
- else:
- data = r.recv(1024)
- if not data:
- rlist.remove(r)
- r.close()
- continue
- print("收到消息:",data.decode())
- # r.send("收到消息".encode())
- wlist.append(r)
- for w in ws:
- w.send("收到消息".encode())
- wlist.remove(w)
- for x in xs:
- x.close()
- raise
来源: http://www.bubuko.com/infodetail-3025983.html