### 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操作 异步阻塞 进程的三状态图