python——通信原理,进程与线程
一、网络编程
1.计算机网络
- 将地理位置不同的具有独立功能地多台计算机及其外部设备,通过通信线路连接起来,在协议的管理和协调下,实现资源共享和信息传递。
网络编程:用来实现网络互连的不同计算机运行程序可以进行数据交换
2.网络模型
计算机网络之间以何种规则进行通信。分为OSI模型和TCP/IP参考模型
2.1OSI:
- 应用层:电脑屏幕看到的东西,产生数据。
- 表示层:做数据进行处理,加密与解密,压缩与解压,编码。
- 会话层:通过传输层建立数据传输的通路,发起会话和接受会话,在传输过程维持会话
- 传输层:数据连接与传输,用一个寻址机制标识一个特定的应用程序(端口)——分成数据段
- 网络层:基于网络层地址(ip地址)进行不同网络系统间的路径选择——进行数据的分割与重新组合,形成新的数据包
- 数据链路层:数据进行mac地址(网卡地址)封装与解封装,使用接收系统的硬件地址和物理地址来寻址,承上启下。——数据帧
- 物理层:物理设备:光纤,同轴电缆,双绞线,网卡,中继器,集线器等——比特数据
2.2TCP/IP:
- 应用层——应用层,表示层,会话层合并——http:超文本传输协议,web服务器之间传输数据的协议,ftp:文件传输协议。smtp:简单邮件传输协议,pop:邮件协议,telent:远程登录协议。DNS:域名系统,域名与IP地址的转换。
- 传输层
- 网络层
- 数据链路层——数据链路层,物理层合并
双方要遵守相同的协议,才能进行信息交流
3.传输层
3.1TCP
- 通过三次握手建立稳定链接。应用数据分割成最合适的数据进行发送
- 连接可靠,不易出现乱序,丢失等现象
- 连接和校验需要时间,效率低下
三次握手
- 客户端发送SYN报文给服务端,进入SYN——SEND状态
- 服务端接收到报文,回应一个SYN ACK报文,进入SYN——RECV状态
- 客户端接收到服务端地SYN报文,回应一个ACK报文,进入连接状态。
3.2UDP
- 一次性发送所有的协议,可能出现数据丢失现象。
4.网络层
有网关,路由器
- IP地址其实是虚拟地址,会通过ARP协议转换为网卡地址
- 计算机只能识别二进制的数据,IP是一个二进制数据。IPV4长度为32位,分为4段,十进制标识。
- IPV6长度是IPV4的四倍,以16进制标识,分为八段,
IP地址:有网络号段和主机号段。127.0.0.1:本机地址,0.0.0.0:任意地址。ping IP地址:测试与该IP地址是否相同
端口是软件的身份证,用来区分不同的软件,最大时2的16次方减一
#服务端配置
import socket
server = socket.socket()
server.bind(('127.0.0.1',8989)) #绑定要运行的服务端的IP地址,端口任意设置
server.listen(10) #设置最大监听数量
result = server.accept() #创建连接通道,获取对等套接字,返回的是一个元组,第一个是对等连接套接字,第二个是客户端的IP加上端口
conn,addr = result #拆包
conn.recv(1024) #设置最大接收字节数
conn.send(b'返回') #返回给客户端数据#数据要对等
conn.close()
server.close()#客户端配置
import socket
client = socket.socket()
client.connect(('127.0.0.1',8989)) #连接服务器开辟出的端口地址
client.send(b'hello') #发送字节数据
client.close()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h2okL5dq-1635859188331)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20211020212829055.png)]
- 传输的必须是字节数据——字符串转字节bytes(info,encoding=‘utf8’)
二、I/O多路复用
1.数据流
- 定义:是一组有序的, 有起点和终点的字节的数据序列,包括输入流和输出流。
- 输入流只能读,不能写,从键盘或文件中获取数据,输出流只能写,不能读,向显示器打印机等写入东西。第一人称是机器。
- I/O——在信息的交换过程中,对这些流进行数据的收发操作。fd就是文件描述符,一个整数,就是对整数的操作。
2.I/O交互
- 用户空间——用户程序和应用程序以及代码
- 内存空间——内核空间,操作系统和驱动程序
- 硬盘空间
3.基本IO模型
IO操作以何种规则进行操作,分为阻塞io,非阻塞io,多路复用io
3.1阻塞IO模型
阻塞IO就是专心做一件事情,阻塞的时候不做其他事情,做完这一件事情,才会去做其他事情。
- 优点:进程阻塞挂起,不会消耗cpu资源,能够及时响应每个操作,难度低
- 缺点:不适合并发量大的应用开发。进程阻塞时不能进行其他操作
#阻塞IO,同时建立两个套接字
import socketserver = socket.socket()
server.bind('127.0.0.1',8989)
server.listen(10)all_conn = []for i in range(2):conn,addr = server.accept()all_conn.append()for conn in all_conn:#得到所有的对等连接套接字data = conn.recv(1024)if data:print(data)else:all_conn.remove(conn)conn.close()
server.close()
3.2非阻塞IO模型
- 优点:在等待线程的时候去做其他任务,效率高。
- 缺点:消耗大,轮询加延迟,而任务可能就在中间任意时间完成
#非阻塞IO
# -*- coding: utf-8 -*-
# @Time: 2021/10/29 19:19
# @Author: 枫无痕
# @Email: thesky_27@163.com
# @File: server01.py
# @Software: PyCharm
import socket
from time import sleep
server = socket.socket()#设置为非阻塞套接字,需要i在其他操作之前设置
server.setblocking(False)server.bind('127.0.0.1',8989)
server.listen(10)# while True:
# try:
# conn,addr = server.accept()
# conn.recv(1024)
# except BlockingIOError:
# print("做其他事情")
# sleep(1)
all_conn = []
while True:try:conn,addr = server.accept()conn.setblocking(False) #将对等套接字设置为非阻塞接字all_conn.append(conn)except BlockingIOError:passexcept Exception as E:print(f"发生了未知异常{E}")#接收数据for conn in all_conn:try:data = conn.recv(1024)if data:print(data)conn.send(data)else:conn.close()all_conn.remove(conn)except BlockingIOError:passexcept Exception as E:print(f"发生了未知异常{E}")
- 同一时间段发生多个事情叫做并发,同一时刻只有一条指令执行,但是是快速的切换执行,宏观是一起执行的,微观不是同时执行的。
- 同一时间点发生多件事情叫做并行。连接客户端和接受数据是并发执行的。
3.3IO多路复用模型
雇佣人来查看与有没有上钩
- 优点:占用资源少,消耗CPU少
- 缺点:需要两个系统调用
原理:select/epoll这个function会不断轮询所负责的socket,有数据之后就会通知用户。
epoll是最佳的打工仔,是一个惰性事件回调,用户自己去调用,是linux最好的IO多路复用器,但是只有linux有。
#多路复用
import socket,selectors #IO多路复用选择器模块,epoll_select = selectors.EpollSelector() #实例化
selectors.DefaultSelector() #默认选择器,自动根据不同操作系统选择
server = socket.socket()
server.bind('127.0.0.1',8989)
server.listen(10)def f_accept(server):conn,addr = server.accept() #生成对等连接套接字epoll_select.register(conn, selectors.EVENT_READ, f_recv)def f_recv(conn):data = conn.recv(1024)if data:print(data)else:conn.close()#selectors.EVENT_READ 有事件发生时,调用回调函数,第三个参数
epoll_select.register(server,selectors.EVENT_READ,f_accept)while True:events = epoll_select.select() #查询,返回的是一个列表,保存一个元组,for key,mask in events:func = key.data #函数体conn = key.fileobj #已经注册的套接字func(conn) #调用f_accept方法。
三、进程与线程
1.CPU时间片
- cpu分配给每个程序的时间,每个线程被分配一个时间段,成为时间片
- 单核CPU只能实现并发,要想真正实现并行,需要多核CPU
2.进程
- 正在运行的程序。一个进程产生一块独立的空间,进程之间相互独立,互不影响
- 时间戳:格林威治时间1970年1月1日0时0分0秒。time.time()——得到时间戳
- time.localtime(time.time())——得到当前的时间。
单进程:就是平常的执行顺序
多进程:就是如下所示
import time
import multiprocessingdef new_time():return time.asctime(time.localtime(time.time()))def func(x,y):print(x+y)print('func_start',new_time())time.sleep(5)print('func_end', new_time())print('main_start',new_time())
p1 = multiprocessing.Process(target=func,args=(1,2))
p1.start()
time.sleep(5)#模拟耗时操作,
print('main_end',new_time())
#一共耗时5秒钟。
- target:表示该进程需要执行的任务,并让子进程执行他所需要的任务。args:需要的是元组类型,并进行参数传递。
- 进程数多于核心数是没有效果的,cpu几核的就是分担几个耗时任务
3.线程
- 一个程序可以有多个进程,每个进程可以有多个线程,但是至少有一个进程和线程。
- 线程共享同个地址空间。
多线程——跟多进程模块是差不多的。
import time
import threadingdef new_time():return time.asctime(time.localtime(time.time()))def func(x,y):print(x+y)print('func_start',new_time())time.sleep(5)print('func_end', new_time())print('main_start',new_time())
p1 = threading.Thread(target=func,args=(1,2))
p1.start()
time.sleep(5)#模拟耗时操作,
print('main_end',new_time())
- 多线程不适合解决计算密集型的情形,但是适合IO密集型的场景
- 因为遇到阻塞会实行自动切换。
GIL全局解释锁——让任何一个进程中只有一个线程去执行。相当于是并发。
4.实现服务器并发
4.1多进程实现并发服务器
import socket
import multiprocessing
'''
主进程左连接客户端,生成对等套接字,通道连接
创建一个子进程,接收客户端
'''
def f_recv(conn):while True:data = conn.recv(1024)if data:print(data)conn.send(data)else:conn.close()breakdef f_accept():sever = socket.socket()sever.bind(('127.0.0.1',4546))sever.listen(10)while True:conn,addr =sever.accept()p1 = multiprocessing.Process(target=f_recv,args=(conn,))p1.start()
if __name__=='__main__':f_accept()
四、进程与线程补充
1.join方法
- 进程或者线程添加join方法后,会等待子任务结束,如果没有结束会一直阻塞,直到子任务结束。
- 一般是放在最后面的。
- 等待子任务结束,进程与线程都有的
import time
import multiprocessingdef new_time():return time.asctime(time.localtime(time.time()))def func(x,y):print(x+y)print('func_start',new_time())time.sleep(5)print('func_end', new_time())print('main_start',new_time())
p1 = multiprocessing.Process(target=func,args=(1,2))
p1.start()
p1.join() #等待子任务执行完毕,会进行阻塞
time.sleep(5)#模拟耗时操作,
print('main_end',new_time())
2.获取当前进程
import time
import multiprocessingdef new_time():return time.asctime(time.localtime(time.time()))def func(x,y):print(x+y)print('func_start',new_time())time.sleep(5)print('func_end', new_time())
if __name__ == '__main__':print(multiprocessing.current_process()) #获取当前进程对象print('main_start',new_time())p1 = multiprocessing.Process(target=func,args=(1,2))p1.start()p1.join() #等待子任务执行完毕,会进行阻塞time.sleep(5)#模拟耗时操作,print('main_end',new_time())
3.获取子进程的名字
import time
import multiprocessingdef new_time():return time.asctime(time.localtime(time.time()))def func(x,y):print(x+y)print('func_start',new_time())time.sleep(5)print('func_end', new_time())
if __name__ == '__main__':print('main_start',new_time())p1 = multiprocessing.Process(target=func,args=(1,2))print(p1.name)p1.name='进程一号'print(p1.name)p1.start()time.sleep(5)#模拟耗时操作,print('main_end',new_time())
4.终止任务
- 可以在主进程结束之后,强制结束子进程
- 但是线程不能终止,只能等待结束。
import time
import multiprocessingdef new_time():return time.asctime(time.localtime(time.time()))def func(x,y):print(x+y)print('func_start',new_time())time.sleep(5)print('func_end', new_time())
if __name__ == '__main__':print('main_start',new_time())p1 = multiprocessing.Process(target=func,args=(1,2))p1.start()time.sleep(5)#模拟耗时操作,p1.terminate() #终止p1子进程print('main_end',new_time())
5.进程的PID
- 在Linux1中,只要进程一创建,系统就会分配一个PID,在运行过程中,PID不会改变。
- 可以通过PID查看进程对资源的使用情况,也可以控制进程的运行.
- 进程的pid是不会改变的,只有在start后才能有pid
import time
import multiprocessingdef new_time():return time.asctime(time.localtime(time.time()))def func(x,y):print(x+y)print('func_start',new_time())time.sleep(5)print('func_end', new_time())
if __name__ == '__main__':print('main_start',new_time())p1 = multiprocessing.Process(target=func,args=(1,2))print('before start',p1.pid)p1.start()print('after start', p1.pid)time.sleep(5)#模拟耗时操作,p1.terminate() #终止p1子进程print('main_end',new_time())
6.线程的ident
- 类似于操作系统中进程的pid,是python解释器分配的。
- 进程是操作系统分配的。
7.生存周期
import time
import multiprocessingdef new_time():return time.asctime(time.localtime(time.time()))def func(x,y):print(x+y)print('func_start',new_time())time.sleep(5)print('func_end', new_time())
if __name__ == '__main__':print('main_start',new_time())p1 = multiprocessing.Process(target=func,args=(1,2))print(p1.is_alive())p1.start()print(p1.is_alive())p1.join()print(p1.is_alive())time.sleep(5)#模拟耗时操作,print('main_end',new_time())
8.守护模式
- 开启守护模式之后,主进程结束,子进程自动结束。
import time
import multiprocessingdef new_time():return time.asctime(time.localtime(time.time()))def func(x,y):print(x+y)print('func_start',new_time())time.sleep(5)print('func_end', new_time())
if __name__ == '__main__':print('main_start',new_time())p1 = multiprocessing.Process(target=func,args=(1,2),daemon=True) #开启守护模式p1.start()time.sleep(5)#模拟耗时操作,print('main_end',new_time())
五、面向对象编程(代码)
- 自定义进程对象,完成多进程并发操作redis数据库。
- redis高速存储数据库,并发操作。
import redis
import multiprocessing
"""
自定义:通过class关键字定一个类要继承继承类
"""
class RedisProcess(multiprocessing.Process):def __init__(self,db,key,values):super().__init__()#调用父类的方法,创造子进程,实例化创建进程self.connect = redis.StrictRedis(db=db) #本地连接,只需要指定一个数据库就可以self.key = keyself.values = valuesdef set(self):self.connect.set(self.key,self.values)def get(self):return self.connect.get(self.key)def run(self):self.set()self.get()
python——通信原理,进程与线程相关推荐
- 怎么更进一步学python_【百尺竿头,更进一步学Python】Python进阶课程——进程,线程和协程的区别...
本文带来各类奇怪的IT百科知识. [百尺竿头,更进一步学Python]Python进阶课程--进程:线程和协程的区别 现在多进程多线程已经是老生常谈了:协程也在最近几年流行起来.今天我们本文主要介绍进 ...
- 递归锁、信号量、GIL锁、基于多线程的socket通信和进程池线程池
递归锁.信号量.GIL锁.基于多线程的socket通信和进程池线程池 递归锁 死锁现象:是指两个或两个以上的进程和线程因抢夺计算机资源而产生的一种互相等待的现象 from threading impo ...
- python并发编程--进程、线程、协程、锁、池、队列
文章目录 操作系统的概念 进程 multiprocessing模块 守护进程 使用多进程实现一个并发的socket的server 锁 生产者消费者模型 数据共享 线程threading模块 守护线程和 ...
- Linux 操作系统原理 — 进程与线程管理
目录 文章目录 目录 前言 进程与线程 内核线程,用户线程与轻量级进程 内核线程 轻量级进程 用户线程 轻量级进程与用户线程的区别 用户线程与轻量级进程的混合模式 用户线程和内核线程的区别 线程的实现 ...
- Python中的进程和线程
一.Python中两种创建进程的方式 1.os.fork只适用于Linux/Mac 2.使用multiprocessing模块可以跨平台实现多进程 使用os.fork(),像Linux平台上那样创建多 ...
- Python基础:进程、线程、协程(2)
进程与线程 什么是进程(process)? An executing instance of a program is called a process. Each process provides ...
- Python中的进程和线程(20)
进程和线程 进程 创建多进程 进程和全局变量 传递参数和进程号 进程的状态 进程之间通信 put() get()方法 生产者和消费者 进程子类化 生产者和消费者子类化 进程池 线程 线程子类化 共享全 ...
- 8-26-GLI锁与普通互斥锁、死锁问题、递归锁、信号量、Event事件、并发的tcp通信、进程池线程池
昨日回顾1 生产者消费者-在生产者和消费者之间,通过队列,增加缓冲,避免了生产者和消费者之间交互-Queue,redis,rabbitmq,kafka-解耦合,队列是微服务的基础2 线程理论,开启-进 ...
- Python 并发1 进程,线程
Python 并发1: 进程,线程 相信大家在操作系统就了解过 进程,线程,死锁,系统调度等等,对基本的概念还是有的.但是,在实践的过程上我在python上的实现却略有不足.所以重新入门Python并 ...
最新文章
- android 连接服务器
- idea远程debug调试阿里云ECS
- python 安装第三方包
- PyTorch深度学习实践03
- SAP成都研究院蓝水晶(Blue Crystall)团队参加米其林全球挑战赛
- mp3 pcm java_Java mp3文件转pcm文件
- 自学python要多久-自学Python多久能找到工作
- 项目管理概论网课作业(用于复习)
- 计算机考试宏的录制,最新版本:鼠标和键盘录制工具(宏录制器)
- 【2019年05月28日】指数估值排名
- xp计算机无法关机,xp系统不能关机解决方法【图文教程】
- 《Python程序设计基础 》课堂笔记整理
- 如何在 Excel 中查找合并的单元格(并删除它们)
- Nuclei Studio IDE 安装及导入项目
- gt9xx linux 移植_GT9XX驱动移植说明书_for_Android_2014011401.pdf
- 解决Linux依赖包的烦恼,教你如何打包依赖,覆盖常用Linux
- 【EMC】脉冲群Burst
- sm3算法 java_“国密加密算法”SM系列的C#实现方法
- 地名Java_ArcGIS For JavaScropt Geocoder —— 搜索地名
- 图片的多点触控缩放与移动