python 网编并发 练习
目录
- 简述 OSI 七层协议 用了什么协议
- 什么是C/S和B/S架构?
- 简述 三次握手、四次挥手的流程。
- TCP和UDP的区别?
- 为何基于tcp协议的通信比基于udp协议的通信更可靠?
- 什么是socket?简述基于tcp协议的套接字通信流程。
- 什么是粘包? socket 中造成粘包的原因是什什么? 哪些情况会发生粘包现象?怎么解决
- IO多路复的作用?
- 什么是防火墙以及作用?
- 简述 进程、线程、协程的区别 以及应用场景?
- GIL锁是什么?会影响效率吗
- 如何创建一个进程线程
- 进程对象join方法
- 僵尸 孤儿 守护进程(liunx中)
- Python中如何使用线程池和进程池?
- 进程之间如何进行通信?
- 多道技术
- 串行 并发 并行 阻塞 非阻塞
- 回调函数
- 进程锁和线程锁的作用?
- 同步 异步 阻塞 非阻塞?
- 路由器和交换机的区别
- 什么是域名解析?
- 如何修改本地hosts件?
- 生产者消费者模型应用场景及优势?
- 什么是cdn?
- LVS是什么及作用?
- 队列 栈 event 事件
简述 OSI 七层协议 用了什么协议
应⽤层 ⽹络服务与最终⽤户的⼀个接⼝。
常⻅协议:HTTP 自己定义的协议
表示层
数据的表示、安全、压缩。(在五层模型⾥⾯已经合并到了应⽤层)
会话层 建⽴、管理、终⽌会话。(在五层模型⾥⾯已经合并到了应⽤层)
对应主机进程,指本地主机与远程主机正在进⾏的会话
抽象层
socket(抽象层)
传输层 定义传输数据的协议端⼝号,以及流控和差错校验。
常⻅协议:TCP UDP,端口协议
常⻅的物理设备 :四层路由器、四层交换机
⽹络层 进⾏逻辑地址寻址,实现不同⽹络之间的路径选择。
常⻅协议:ip协议(分配ip找到局域网)
常⻅物理设备:路由器、三层交换机
数据链路层
常⻅协议:ARP协议(找mac) 以太网协议(对比特流数据进行分组)
常⻅物理设备:⽹桥、以太⽹交换机、⽹卡
物理层
建⽴、维护、断开物理连接。(由底层⽹络定义协议)
常⻅物理设备:中继器、集线器、双绞线
什么是C/S和B/S架构?
c/s架构,就是client(客户端)与server(服务端)即:客户端与服务端的架构。
b/s架构,就是brosver(浏览器端)与sever(服务端)即:浏览器端与服务端架构
优点:统一了所有应用程序的入口、方便、轻量级
简述 三次握手、四次挥手的流程。
三次握手:
第一次握手
1:客户端先向服务端发起一次询问建立连接的请求,并随机生成一个值作为标识
第二次握手
2:服务端向客户端先回应第一个标识,再重新发一个确认标识
第三次握手
3:客户端确认标识,建立连接,开始传输数据
四次挥手 ---> 断开连接
第一次挥手
客户端向服务端发起请求断开连接的请求
第二次挥手
服务端向客户端确认请求
第三次挥手
服务端向客户端发起断开连接请求
第四次挥手
客户端向服务端确认断开请求
TCP和UDP的区别?
TCP/UDP区别
TCP协议是面向连接,保证高可靠性传输层协议
UDP:数据丢失,无秩序的传输层协议(qq基于udp协议)
为何基于tcp协议的通信比基于udp协议的通信更可靠?
tcp:可靠,因为只要对方回了确认收到信息,才发下一个,如果没收到确认信息就重发
UDP:不可靠,它是一直发数据,不需要对方回应
流式协议: TCP协议,可靠传输
数据报协议: UDP协议,不可靠传输
什么是socket?简述基于tcp协议的套接字通信流程。
1.Socket又称为套接字,它是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口提高了效率
2.socket就是一个模块。我们通过调用模块中已经实现的方法建立两个进程之间的连接和通信。也
为什么存在socket抽象层?
3.如果直接与操作系统数据交互非常麻烦,繁琐,socket对这些繁琐的的操作高度的封装,简化.
4.socket在python中就是一个模块.
服务端:
创建socket对象,
绑定ip端口bind(),
设置最大链接数listen(),
accept()与客户端的connect()创建双向管道,等到联接,
send(), recv(), 收发数据
close()
客户端:
创建socket对象,
connect()与服务端accept()创建双向管道 ,
send(),
recv(),
close()
什么是粘包? socket 中造成粘包的原因是什什么? 哪些情况会发生粘包现象?怎么解决
只有TCP有粘包现象,UDP永远不会粘包
粘包:在获取数据时,出现数据的内容不是本应该接收的数据,如:对方第一次发送hello,第二次发送world,
我方接收时,应该收两次,一次是hello,一次是world,但事实上是一次收到helloworld,一次收到空,这种现象叫粘包
原因
粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。
什么情况会发生:
1、发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)
2、接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,
服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)
自定义报头
#第一步制作报头 head 头 #第2步将字典转为json字符串 #第3步 将json字符串 转为 byes类型 #第4步将json的byres 长度转为固定4个 byres #第5步 发送 固定4个byres total_size_byres #第6步 发送字典byres 给客服端 # 第7步 发送原内容 给客服端
IO多路复的作用?
I/O多路复用是用于提升效率,单个进程可以同时监听多个网络连接IO。
socketserver,多个客户端连接,单线程下实现并发效果,就叫多路复用。
与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。
什么是防火墙以及作用?
防火墙是一个分离器、一个限制器,也是一个分析器,有效地监控了内部网和Internet之间的任何活动,保证了内部网络的安全
作用
防火墙是网络安全的屏障
可以强化网络安全策略
对网络存取和访问进行监控审计
防止内部信息的外泄
除了安全作用,防火墙还支持具有Internet服务特性的企业内部网络技术体系VPN(虚拟专用网)。
简述 进程、线程、协程的区别 以及应用场景?
进程
1.资源分配的最小单位 开销大
2.进程之间数据不能直接共享
3.开启多进程的速度慢
4.可以利用多核
线程
1.操作系统调度(给CPU执行)的最小单位 开销非常小
2.同一个进程下的线程之间的数据可以共享
3.开启多线程速度快.
4.不可以利用多核
协程
1.协程本质上就是一个线程 一个线程实现并发.如果协程中处理的所有任务都遇到了阻塞 协程就会停止 只有阻塞完成会切回来 进程间是由操作系统调控cpu 而协程是由我们自己书写的程序调控的
2.单核心下处理多任务最好的方式,协程 开销小. 运行速度快. 协程会长期霸占cpu只执行我程序里面的所有任务.
必须在只有一个单线程里实现并发
修改共享数据不需加锁
用户程序里自己保存多个控制流的上下文栈(保持状态)
附加:一个协程遇到IO操作自动切换到其它协程
应用场景
多线程用于IO密集型,如socket,爬虫,web
多进程用于计算密集型,如金融分析
1. 每个cpython进程内都有一个GIL
2. GIL导致同一进程内多个进程同一时间只能有一个运行
3. 之所以有GIL,是因为Cpython的内存管理不是线程安全的
4. 对于计算密集型用多进程,多IO密集型用多线程
GIL锁是什么?会影响效率吗
来源是python设计之初的考虑,为了数据安全所做的决定
GIL本质就是一把互斥锁,既然是互斥锁,所有互斥锁的本质都一样,都是将并发运行变成串行,以此来控制同一时间内共享数据只能被一个任务所修改,进而保证数据安全。
GIL保护的是解释器级的数据,保护用户自己的数据则需要自己加锁处理
Jpython没有GIL锁.
pypy也没有GIL锁.
在io密集型不会影响 计算型会影响
如何创建一个进程线程
第一种 利用python中模块Process类创建 通过调用multiprocessing模块下面的Process类方法
第2种 自己定义一个类 继承与Process 重写run 方法 run方法里面是自己写的逻辑代码 方式二借助process类,自定义一个类(继承Process),从而造一个对象 并重新run方法
进程的创建.
想开启多个进程,必须是一个主进程,开启多个子进程.
unix: fork创建子进程.
windows:操作系统调用CreateProcess处理进程的创建.
linux, windows: 由主进程开启子进程:
相同点: 原则:主进程开启子进程两个进程都有相互隔离的独立的空间,互不影响.
不同点:
linux: 子进程空间的初始数据完全是从主(父)进程copy一份.
windows: 子进程空间的初始数据完全是从主(父)进程copy一份,但是有所不同.
进程对象join方法
join让主进程等待我这个 进程结束之后,在执行主进程. 相当与阻塞
僵尸 孤儿 守护进程(liunx中)
# linux(mac)环境下才强调的两个概念,windows下没有.
基于unix环境(linux,macOS)
为什么会产生僵尸进程??
主进程需要等待子进程结束之后,主进程才结束
主进程时刻监测子进程的运行状态,当子进程结束之后,一段时间之内,将子进程进行回收.
为什么主进程不在子进程结束后马上对其回收呢?
主进程与子进程是异步关系.主进程无法马上捕获子进程什么时候结束.
如果子进程结束之后马上再内存中释放资源,主进程就没有办法监测子进程的状态了.
unix针对于上面的问题,提供了一个机制.
所有的子进程结束之后,立马会释放掉文件的操作链接,内存的大部分数据,但是会保留一些内容: 进程号,结束时间,运行状态,等待主进程监测,回收.
孤儿进程
父进程由于某种原因结束了,但是你的子进程还在运行中,这样你的这些子进程就成了孤儿进程.你的父进程如果结束了,你的所有的孤儿进程就会被init进程的回收,init就变成了你的父进程,对你进行回收.
僵尸进程
1.僵尸进程: 所有的子进程结束之后,在被主进程回收之前,都会进入僵尸进程状态
2.僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。如果父进程先退出 ,子进程被init接管,子进程退出后init会回收其占用的相关资源
僵尸进程有无危害???
如果父进程不对僵尸进程进行回收(wait/waitpid),产生大量的僵尸进程,这样就会占用内存,占用进程pid号.
僵尸进程如何解决???
父进程产生了大量子进程,但是不回收,这样就会形成大量的僵尸进程,解决方式就是直接杀死父进程,将所有的僵尸进程变成孤儿进程进程,由init进行回收.
守护进程
守护进程不可以有子进程 否则抛异常
被守护进程运行完成 同时守护进程 同时完结 不管守护进程还有没有执行完
守护进程先完结就没有守护的意义
# p.daemon = True # 将p子进程设置成守护进程,守护主进程,只要主进程结束,子进程无论执行与否,都马上结束.一定要在发起前
# 必须在发起前守护 多用于窗口化
下面验证了守护进程运行完就完了 对被守护的没影响
Python中如何使用线程池和进程池?
提高效率
什么时候用池:
池的功能是限制启动的进程数或线程数,
什么时候应该限制???
当并发的任务数远远超过了计算机的承受能力时,即无法一次性开启过多的进程数或线程数时
就应该用池的概念将开启的进程数或线程数限制在计算机可承受的范围内
进程之间如何进行通信?
基于文件
管道
队列
第3方模块
多道技术
多道技术要求物理层面实现进程之间内存的隔
多道技术解决了什么:
时间上的复用 将串行变为并发
空间上的复用.一个内存允许加载多个进程.
阻塞; IO阻塞,recv, accept, read input,write, sleep等等,都是阻塞.
如果三个进程全部都没有IO阻塞,多道技术就会影响最终的效率.
串行 并发 并行 阻塞 非阻塞
串行: 所有的进程由cpu一个一个的解决.
并发:单个cpu,同时执行多个进程(来回切换的),看起来像是同时运行.
并行:多个cpu,真正的同时运行多个进程.
阻塞:遇到IO才叫阻塞.
非阻塞: 没有IO.
进程3个状态 运行 就绪 阻塞
回调函数
当一个任务完成之后,将parse这个分析代码的任务交由剩余的空闲的线程去执行,你这个线程继续去处理其他任务
如果进程池+回调: 回调函数由主进程去执行.
如果线程池+回调: 回到函数由空闲的线程去执行.
进程锁和线程锁的作用?
线程锁:
多线程可以同时运行多个任务但是当多个线程同时访问共享数据时,可能导致数据不同步,甚至错误! so,不使用线程锁, 可能导致错误
大家都不陌生,主要用来给方法、代码块加锁。当某个方法或者代码块使用锁时,那么在同一时刻至多仅有有一个线程在执行该段代码。
当有多个线程访问同一对象的加锁方法/代码块时,同一时间只有一个线程在执行,其余线程必须要等待当前线程执行完之后才能执行该代码段。但是,其余线程是可以访问该对象中的非加锁代码块的。
进程锁:
也是为了控制同一操作系统中多个进程访问一个共享资源,
只是因为程序的独立性,各个进程是无法控制其他进程对资源的访问的,
但是可以使用本地系统的信号量控制(操作系统基本知识)。
优点:保证资源同步
缺点:有等待肯定会慢
同步 异步 阻塞 非阻塞?
在执行的角度
阻塞:程序运行时遇到了IO,程序挂起,cpu被切走.
非阻塞:程序没有遇到I0,程序遇到10但是我通过某种手段,让cpu 强行运行我的程序.
在发起的角度
同步:提交-个任务 自任务开始运行直到此任务结束(可能有I0),返回一个返回值之后,我在提交下一个任务.
异步:一次提交多个任务然后我就直接执行下一行代码.
路由器和交换机的区别
1:交换机:是负责内网里面的数据传递(arp协议)根据MAC地址寻址
路由器:在网络层,路由器根据路由表,寻找该ip的网段
2:路由器可以处理TCP/IP协议
3:路由器可以把一个IP分配给很多个主机使用,这些主机对外只表现出一个IP。
交换机可以把很多主机连起来,这些主机对外各有各的IP。
4:交换机是做端口扩展的,也就是让局域网可以连进来更多的电脑。
路由器是用来做网络连接,也就是;连接不同的网络
什么是域名解析?
在互联网上,所有的地址都是ip地址,现阶段主要是IPv4(比如:110.110.110.110)。
但是这些ip地址太难记了,所以就出现了域名(比如http://baidu.com)。
域名解析就是将域名,转换为ip地址的这样一种行为。
如何修改本地hosts件?
Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,
当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,
一旦找到,系统会立即打开对应网页,如果没有找到,则系统会再将网址提交DNS域名解析服务器进行IP地址的解析。
浏览器访问网站,要首先通过DNS服务器把要访问的网站域名解析成一个唯一的IP地址,之后,浏览器才能对此网站进行定位并且访问其数据。
文件路径:C:\WINDOWS\system32\drivers\etc。
将127.0.0.1 www.163.com 添加在最下面
修改后用浏览器访问“www.163.com”会被解析到127.0.0.1,导致无法显示该网页。
生产者消费者模型应用场景及优势?
生产者与消费者模式是通过一个容器来解决生产者与消费者的强耦合关系,生产者与消费者之间不直接进行通讯,
而是利用阻塞队列来进行通讯,生产者生成数据后直接丢给阻塞队列,消费者需要数据则从阻塞队列获取,
实际应用中,生产者与消费者模式则主要解决生产者与消费者生产与消费的速率不一致的问题,达到平衡生产者与消费者的处理能力,而阻塞队列则相当于缓冲区。
应用场景:用户提交订单,订单进入引擎的阻塞队列中,由专门的线程从阻塞队列中获取数据并处理
优势:
1;解耦
假设生产者和消费者分别是两个类。如果让生产者直接调用消费者的某个方法,那么生产者对于消费者就会产生依赖(也就是耦合)。
将来如果消费者的代码发生变化,可能会影响到生产者。而如果两者都依赖于某个缓冲区,两者之间不直接依赖,耦合也就相应降低了。
2:支持并发
生产者直接调用消费者的某个方法,还有另一个弊端。由于函数调用是同步的(或者叫阻塞的),在消费者的方法没有返回之前,生产者只能一直等着
而使用这个模型,生产者把制造出来的数据只需要放在缓冲区即可,不需要等待消费者来取
3:支持忙闲不均
缓冲区还有另一个好处。如果制造数据的速度时快时慢,缓冲区的好处就体现出来了。
当数据制造快的时候,消费者来不及处理,未处理的数据可以暂时存在缓冲区中。等生产者的制造速度慢下来,消费者再慢慢处理掉。
什么是cdn?
目的是使用户可以就近到服务器取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。
cdn 即内容分发网络
LVS是什么及作用?
LVS :Linux虚拟服务器
作用:LVS主要用于多服务器的负载均衡。
它工作在网络层,可以实现高性能,高可用的服务器集群技术。
它廉价,可把许多低性能的服务器组合在一起形成一个超级服务器。
它易用,配置非常简单,且有多种负载均衡的方法。
它稳定可靠,即使在集群的服务器中某台服务器无法正常工作,也不影响整体效果。另外可扩展性也非常好。
队列 栈 event 事件
线程队列
FIFO队列
# 1 FIFO队列 queue 先进先出 特殊参数 block=True, timeout=None
LIFO 栈
# LIFO 栈. 先进后出 特殊参数 block=True, timeout=None
LIFO 栈
# LIFO 栈. 先进后出 特殊参数 block=True, timeout=None
事件Event
并发的执行某个任务 .多线程多进程,几乎同时执行.
一个线程执行到中间时遇到事件event通知另一个线程开始执行.
会自动轮询检测
非学,无以致疑;非问,无以广识