### 8.8 网络基础知识
#### 8.8.1 网络应用开发架构
C/S架构:迅雷 浏览器 飞秋 输入法 百度云 各种游戏
- client 客户端
- server 服务区
B/S构架: 淘宝 邮箱 各种游戏 百度 博客园 知乎 豆瓣
- browser 浏览器
- server 服务器
B/S是特殊的C/S架构
#### 8.8.2 ip
网络:一个实际存在计算机中的硬件
mac地址:每一块网卡上都有一个全球唯一的mac地址
交换机:是连接多台机器并帮助通讯的物力设备,只认识mac地址
协议:两台物理设备之间对于要发送的内容,长度,顺序等的一些约定
ip地址:
- ipv4协议 位的点分十进制 32位二进制
- 0.0.0.0——255.255.255.255
- ipv6协议 6位的冒分十六进制 128位二进制表示
- 0:0:0:0:0:0——FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
问题:为什么你外地朋友的电脑我们访问不了
- 答:每一个ip地址想要被所有人访问到,那么这个ip地址就必须申请
内网:
```
# 192.168.0.0 - 192.168.255.255
# 172.16.0.0 - 172.31.255.255
# 10.0.0.0 - 10.255.255.255
```
交换机实现的arp协议
- 通过ip地址过去一台机器的mac地址
网管ip:一个局域网的出口,访问局域网之外的区域都要经过路由器和网关
网段:指的是一个地址段 x.x.x.0 x.x.0.0 x.0.0.0
子网掩码:判断两台机智是否在同一个网段内的
port 端口,每台电脑上有很多个端口,同一时间一个应用只能对应一个端口
ip地址 + 端口就可以确认一台机器的一个应用
### 8.9 tcp协议和udp协议
#### 8.9.1 tcp协议 -------打电话
特点:
- 可靠 慢 全双工通信 流式的
- 建立连接的时候:三次握手
- accept接受过程中等待客户端的连接
- connect客户端发起了一个syn链接请求
- 如果得到了server端响应ack的同时还会在接受一个由server端发送来的syc连接请求
- client端进行回复ack之后,就建立起一个tcp协议的链接
- 三次握手的过程在代码中石油accept和connect共同完成的,具体的细节在socket中没有体现出来
- 断开连接的时候:四次挥手
- server和client端对应的在代码中都有close方法
- 每一段发起的close操作都是一次fin的断开请求,得到“断开确认ack”之后就可以结束一端的数据发送
- 如果两端都发起了close操作,那么两次请求和两次回复,一共就是四次操作
- 可以结束两端的数据发送,表示连接断开
- 长连接:会一直占用双方的端口
- 能够传递的数据长度几乎没有限制
在建立连接之后:
- 发送的每一条信息都有回执
- 为了保证数据的完整,还有重传机制
IO(input,output)操作,输入和输出的相对内存来说的
- write send ------ output
- read recv ----- input
#### 8.9.2 udp协议 ------发短信
特点:
- 无连接的 速度快 不可靠 数据长度小 能完成一对一、一对多、多对一、多对多的高效通讯协议
- 可能会丢消息
- 能够传递的数据长度是有限的,是根据数据传递设备的设置有关系
#### 8.9.3 应用场景
TCP:文件的上传下载(发送邮件、网盘、缓存电影)
UDP:即时通信(qq、微信、飞秋)
#### 8.9.4 osi七层模型
七层模型:
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
五层协议:
- 应用层 python代码
- 传输层 tcp/udp协议 端口
- 网络层 ipv4/ipv6协议
- 数据链路层 mac地址、arp协议、网卡
- 物理层
#### 8.9.5 socket(套接字)
socket:
- 同一台机器的两个服务之间的通信
- 基于网络的多台机器之间的多个服务通信
计算器:
```python
import re
from functools import reduce
def exp_format(exp):
exp = exp.replace('--','+')
exp = exp.replace('+-','-')
exp = exp.replace('++','+')
exp = exp.replace('-+','-')
return exp
def mul_div(atom_exp): # 最基础的两个数的加减乘除
if '*' in atom_exp:
a, b = atom_exp.split('*')
res = float(a) * float(b)
else:
a, b = atom_exp.split('/')
res = float(a) / float(b)
return res
def cal_muldiv(exp): # 匹配乘除法 计算
com = re.compile('\d+(\.\d+)?[*/]-?\d+(\.\d+)?')
while True:
obj = com.search(exp)
if obj:
atom_exp = obj.group()
res = mul_div(atom_exp)
exp = exp.replace(atom_exp,str(res))
else:break
return exp
def cal_addsub(exp): # 计算加减法
ret = re.findall('[-+]?\d+(?:\.\d+)?',exp)
count = reduce(lambda x,y:float(x)+float(y),ret)
return count
# 算式的去空格
exp = '2- -3* -4/ -5*-3 -6'
exp = exp.replace(' ','')
sub_exp = cal_muldiv(exp)
sub_exp = exp_format(sub_exp)
ret = cal_addsub(sub_exp)
print(ret)
```
### 8.10 编码
计算机上的存储和网络上的数据传输都是采用二进制
8位/bit/比特 = 10101001 = 1字节
send:str——>encode(编码)——>bytes
recv: str——>dencode(编码)——>str
### 8.11 struct模块(用于传输)
ret = struct.pack('i',7863) 将后面的数字转化成四个字节表示
struct.unpack('i',ret) 将ret转化成数字
### 8.11 粘包现象
定义:
1.发生在发送端的粘包:
- 由于两个数据发送时间间隔短+数据的长度小
- 所以由tcp协议的优化机智将两条信息作为一条信息发送了出去
- 为了减少tcp协议中的“确认收到”的网络延迟时间
2.发生在接收端的粘包:
- 由于tcp协议中所传输的数据无边界,所以来不及接受的多条数据会在接受的内核缓存断粘在一起
#### 8.11.1 解决粘包现象
自定义协议1:
- 首先发送报头
- 报头长度为4个字节
- 内容是即将发送的报文的字节长度
- struct模块
- pack/unpack 能够将所有的数字都固定转换成四字节或者转回来
- 再发送报文
自定义协议2
- 我们专门用来做文件发送的协议
- 先发送报头字典的字节长度
- 再发送字典(字典中包含文件的名字、大小等等)
- 再发送文件的内容
## 第九章 并发编程
### 9.1操作系统的发展史
1.人机矛盾
- CPU利用率低
2.磁带存储+批处理
- 降低数据的读取时间
- 提高cpu的利用率
3.多道操作系统——在一个任务遇到IO的时候主动让出CPU
- 数据隔离
- 时空复用
- 能够在一个任务遇到IO操作的时候主动吧CPU让出来,给其他的任务使用
4.分时操作系统——给时间分片,让过个任务轮流使用CPU
例子:教授 24h 没有IO
研究生 5min 没有IO
研究生 10min 没有IO
三种算法结合:
- 短作业有限算法
- 先来先服务算法
- 时间分片(每个程序分配一个时间片)
要切换CPU和IO 要占用时间 反而降低了CPU的利用率 但是用户体验上升
分时操作系统+多道操作系统+实时操作系统
- 多个程序一起在计算机中执行
- 一个程序如果遇到IO操作就切出去让出CPU
- 一个程序没有遇到IO,但是时间片到了,切出去让CPU
### 9.2 进程
定义:运行中的程序
程序和进程之间的区别:
- 程序只是一个文件
- 进程是这个文件被CPU运行起来了
进程是计算机中最小的资源分配单位
在操作系统中的唯一标识:pid
操作系统调度进程的算法:
- 短作业优先
- 先来先到服务
- 时间片轮转
- 多级反馈算法
并行与并发:
- 并行
- 两个程序,两个CPU,每个程序分别占用一个CPU自己执行自己的
- 看起来是同时执行,实际上在每一个时间点上都有各自执行的各自的
- 并发
- 两个程序,一个CPU,每个程序交替的在一个CPU上执行
- 看起来是同时执行,但实际上任然是串行
同步与异步:
- 同步:停下当前的程序去执行另一个,共用一个CPU
- 异步:同时用不同的CPU
阻塞与非阻塞
- 阻塞:CPU不工作
- 非阻塞:CPU工作
同步阻塞
- conn.recv
- socket 阻塞的tcp协议的时候
同步非阻塞
- func() 没有io操作
- socket 非阻塞的tcp协议的时候
- 调用函数(这个函数内部不存在io操作)
异步非阻塞
- 把func扔到其他任务里去执行了
- 我本身的任务和func任务各自执行各自的 没有io操作
异步阻塞
进程的三状态图