UDP代码编写、操作系统发展史、多道技术、进程理论与代码层面创建、进程join方法与进程对象方法
昨日内容回顾
socket基本使用
# 内置的模块
import socket
s = socket.socket() # 默认是TCP协议 也可以切换为UDP协议
s.bind((ip,port))
s.listen(5)
sock,addr = s.accept()
sock.recv(1204)
sock.send(b'hello')
c = socket.socket()
c.connect((ip,port))
...
通信循环
将recv和send代码区加上while循环即可
链接循环
将监听代码区加上while循环即可
代码健壮性校验
1.异常捕获
2.端口冲突
3.系统问题
在客户端判断用户输入是否为空 continue
在服务端判断接收的消息是否为空 break
TCP黏包特性
1.双向通道中数据量较大有残余
2.TCP会将数据量较小并且时间间隔较短的数据一次性打包发送(流式协议)
如何解决黏包问题
制作报头:固定长度 内部含有诸多信息
能够固定打包数据的模块struct模块
客户端
1.打包固定长度的字典的报头并发送
2.发送字典数据
3.发送真实数据
服务端
1.先接收固定长度的报头 4
2.解析报头获取字典长度 255
3.接收字典数据并解析数据从中获取真实数据相关的信息
4.接收真实数据
大文件传输
1.如何校验文件数据的一致性
使用hashlib模块对文件内容做加密处理比对处理之后的随机字符串(耗时)
切片加密比对
读取文件部分内容加密(比如划分十块区域)
2.数据存储
for循环一行行发送并一行行存储
今日内容概要
- UDP代码编写(了解即可)
- 计算机核心理论(发展史)
- 进程理论
- 开启进程的诸多方式
- 进程join方法
- 进程间数据隔离
- IPC机制
内容详细
1、UDP代码编写
# 服务端
import socket
udp_sk = socket.socket(type=socket.SOCK_DGRAM) # UDP协议
udp_sk.bind(('127.0.0.1', 9000)) # 绑定地址
msg, addr = udp_sk.recvfrom(1024) # 获取客户端说的话和地址
udp_sk.sendto(b'hi', addr) # 向客户端说话
udp_sk.close()
# 客户端
import socket
ip_port = ('127.0.0.1', 9000) # 想访问的服务端地址
udp_sk = socket.socket(type=socket.SOCK_DGRAM)
udp_sk.sendto(b'hello', ip_port) # 向ip_port说话
back_msg, addr = udp_sk.recvfrom(1024) # 获取服务端回复的话和服务端地址
print(back_msg.decode('utf-8'), addr)
"""
时间服务器的实现原理
1.内部小电容供电
2.远程时间同步
"""
2、操作系统发展史
"""学习并发编程其实就是在学习操作系统的发展史(底层逻辑)"""
# 1.穿孔卡片时代
CPU的利用率极低
# 2.联机批处理系统
将多个程序员的程序一次性录入磁带中 之后交由输入机输入并由CPU执行
# 3.脱机批处理系统
现代计算机的雏形(远程输入 高速磁带 主机)
- 穿孔卡片时代
- 联机批处理系统
- 脱机批处理系统
3、多道技术
'''针对处理器单核的情况'''
# 1.单道技术:
主要是串行状态 cpu利用率极低
# 2.多道技术
切换+保存状态 提升cpu利用率
"""
CPU工作机制
1.当某个程序进入IO(输入输出)状态的时候 操作系统会自动剥夺该程序的CPU执行权限
2.当某个程序长时间占用CPU的时候 操作系统也会剥夺该程序的CPU执行权限
"""
# 3.并行与并发
并行:多个程序同时执行(针对多核处理器)
并发:多个程序只要看起来像同时运行即可(针对单核处理器)
'''
单核CPU能否实现并行?
肯定不能,但是可以实现并发
12306可以同一时间支持几个亿的用户买票 问是并行还是并发?
肯定是并发(高并发)
星轨:微博(高并发)能够支持八个星轨(明星出轨)
'''
4、进程理论
# 1.进程与程序的区别(总结)
程序:一堆代码(死的)
进程:正在运行的程序(活的)
# 2.单核情况下的进程调度
要想多个进程交替运行,操作系统必须对这些进程进行调度,这个调度也不是随即进行的,而是需要遵循一定的法则,由此就有了进程的调度算法
进程调度算法演变:
1.FCFS 先来先服务
对短作业不友好
2.短作业优先调度算法
对长作业不友好
3.时间片轮转法+多级反馈队列
先分配给新的多个进程相同的时间片
之后根据进程消耗的时间片多少分类别
每次有新的进程要启动 都会重新分配时间片
需要消耗更长时间启动的进程
会参与每次时间片的获取
每次获取时间片后的进度会被保留 并反馈给CPU
在下次分配时间片时会 在原进度基础上继续获取
直至启动完成
......
# 3.进程三状态
就绪态 运行态 阻塞态
'''进程要想进入运行态必须先经过就绪态'''
# 4.同步与异步
'''用于描述任务的提交方式'''
同步:提交完任务之后原地等待任务的返回结果 期间不做任何事
异步:提交完任务之后不原地等待任务的返回结果 直接去做其他事 结果由反馈机制自动提醒
# 5.阻塞与非阻塞
'''用于描述任务的执行状态'''
阻塞:阻塞态
非阻塞:就绪态 运行态
# 同步阻塞形式
效率最低
就是你专心排队,什么别的事都不做
# 异步阻塞形式
如果在银行等待办理业务的人采用的是异步的方式去等待消息被触发(通知),也就是领了一张小纸条,假如在这段时间里他不能离开银行做其它的事情,那么很显然,这个人被阻塞在了这个等待的操作上面
异步操作是可以被阻塞住的,只不过它不是在处理消息时阻塞,而是在等待消息通知时被阻塞
# 同步非阻塞形式
实际上是效率低下的
想象一下你一边打着电话一边还需要抬头看到底队伍排到你了没有,如果把打电话和观察排队的位置看成是程序的两个操作的话,这个程序需要在这两种不同的行为之间来回的切换,效率可想而知是低下的
# 异步非阻塞形式
效率更高
因为打电话是你(等待者)的事情,而通知你则是柜台(消息触发机制)的事情,程序没有在两种不同的操作中来回切换
比如说,这个人突然发觉自己烟瘾犯了,需要出去抽根烟,于是他告诉大堂经理说,排到我这个号码的时候麻烦到外面通知我一下,那么他就没有被阻塞在这个等待的操作上面,自然这个就是异步+非阻塞的方式了
"""
很多人会把同步和阻塞混淆,是因为很多时候同步操作会以阻塞的形式表现出来,同样的,很多人也会把异步和非阻塞混淆,因为异步操作一般都不会在真正的IO操作处被阻塞
"""
4.1、创建进程
1. 在UNIX中该系统调用是:fork,fork会创建一个与父进程一模一样的副本,二者有相同的存储映像、同样的环境字符串和同样的打开文件(在shell解释器进程中,执行一个命令就会创建一个子进程)
2. 在windows中该系统调用是:CreateProcess,CreateProcess既处理进程的创建,也负责把正确的程序装入新进程。
"""
关于创建子进程,UNIX和windows
1.相同的是:进程创建后,父进程和子进程有各自不同的地址空间(多道技术要求物理层面实现进程之间内存的隔离),任何一个进程的在其地址空间中的修改都不会影响到另外一个进程
2.不同的是:在UNIX中,子进程的初始地址空间是父进程的一个副本,提示:子进程和父进程是可以有只读的共享内存区的。但是对于windows系统来说,从一开始父进程与子进程的地址空间就是不同的
"""
4.2、代码层面创建进程
# 创建进程方式一:
import os
from multiprocessing import Process
import time
def test(name):
print('%s正在运行' % name)
time.sleep(3)
print('%s已经结束' % name)
if __name__ == '__main__':
p = Process(target=test, args=('jason',)) # 生成一个进程对象
p.start() # 告诉操作系统开设一个新的(子)进程 异步提交
print(os.getpid()) # 获取子进程号
print(os.getppid()) # 获取父进程号
print('主')
执行结果:
11876
7404
主 # 主程序不会等子程序执行完毕后再执行
jason正在运行
jason已经结束
"""
在windows中开设进程类似于导入模块
从上往下再次执行代码
一定需要在__main__判断语句内执行开设进程的代码
在linux中是直接将代码完整的复制一份执行
不需要在__main__判断语句内执行
"""
# 创建进程方式二:
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self, name):
super().__init__()
self.name = name
def run(self): # 固定格式 用 run
print('%s正在运行' % self.name)
time.sleep(3)
print('%s已经结束' % self.name)
if __name__ == '__main__':
p = MyProcess('jack')
p.start()
print('主进程')
执行结果:
主进程 # 主程序不会等子程序执行完毕后再执行
jack正在运行
jack已经结束
4.3、进程的join方法
'''
要求:
主进程执行结果要在子进程执行完毕之后(串行)
'''
# 1.验证join方法
from multiprocessing import Process
import time
def test(name):
print('%s开始运行' % name)
time.sleep(3)
print('%s结束' % name)
if __name__ == '__main__':
p = Process(target=test, args=('jason',))
p.start()
p.join() # 等待子进程运行完毕之后 再继续运行主进程代码(串行)
print('主进程')
# 执行结果: # 主进程等待子进程执行完毕之后再继续执行
jason开始运行
jason结束
主进程
# 2.验证p.start()功能
from multiprocessing import Process
import time
def test(name):
print('%s开始运行' % name)
time.sleep(3)
print('%s结束' % name)
if __name__ == '__main__':
p = Process(target=test, args=('jason',))
p1 = Process(target=test, args=('tony',))
p2 = Process(target=test, args=('ly',))
p.start()
p1.start()
p2.start()
p.join() # 等待子进程运行完毕之后 再继续运行主进程代码(串行)
print('主进程')
执行结果: # 随机运行子进程
tony开始运行
jason开始运行
ly开始运行
jason结束
tony结束
ly结束
主进程
# 3.验证join方法的串行状态
from multiprocessing import Process
import time
def test(name):
print('%s开始运行' % name)
time.sleep(3)
print('%s结束' % name)
if __name__ == '__main__':
start_time = time.time()
for i in range(1, 4):
p = Process(target=test, args=(i, ))
p.start()
p.join() # 等待子进程运行完毕之后 再继续运行主进程代码(串行)
print(time.time() - start_time)
执行结果: # 每个子进程都是三秒时间 主进程结束至少9秒以上
1开始运行
1结束
2开始运行
2结束
3开始运行
3结束
9.431007862091064
# 4.提升CPU效率 解决串行状态的无效等待
from multiprocessing import Process
import time
def test(name, n):
print('%s开始运行' % name)
time.sleep(n)
print('%s结束' % name)
if __name__ == '__main__':
p_list = []
start_time = time.time()
for i in range(1, 4):
p = Process(target=test, args=(i, i))
p.start()
p_list.append(p)
for p in p_list:
p.join()
print(time.time() - start_time) # 主程序执行时间 永远依据需要最长时间的子进程 而不是所有进程时间相加
执行结果:
1开始运行
2开始运行
3开始运行
1结束
2结束
3结束
3.1535840034484863
4.4、进程间默认无法交互
# 进程间数据是相互隔离的
from multiprocessing import Process
money = 100
def test():
global money
money = 999
if __name__ == '__main__':
p = Process(target=test)
p.start()
# 先确保子进程运行完毕了 再打印
p.join()
print(money)
执行结果:
100
'''
因为start启动进程 原理是 按照导入模块的方式从上自下执行代码
在test()中执行的global 只是更改了子进程自己的全局money
最后的print(money) 输出的是主进程的 money 所以结果没变
证明 子进程和主进程之间的数据是无法交互的
'''
"""
如果在局部修改全局数据:
如果数据为不可变类型 则需要使用关键字 global 声明
如果数据为可变类型 则无需使用关键字 global 声明
如果想要在内部的局部修改外部局部的不可变数据类型:
需要关键字nonlocal声明
"""
5、进程对象方法
1.current_process查看进程号
2.os.getpid() 查看进程号 os.getppid() 查看父进程进程号
from multiprocessing import current_process
import os
print(os.getpid()) # 11660 获取当前进程号
print(os.getppid()) # 7404 获取当前进程父进程编号
print(current_process().pid) # 11660 获取当前进程号
3.进程的名字,p.name直接默认就有,也可以在实例化进程对象的时候通过关键字形式传入name=''
4.p.terminate() 杀死子进程
5.p.is_alive() 判断进程是否存活
from multiprocessing import Process
import time
def test(name, n):
print('%s开始运行' % name)
time.sleep(n)
print('%s结束' % name)
if __name__ == '__main__':
p = Process(target=test, args=('jason', 3))
p.start()
p.terminate() # 杀死子进程
time.sleep(0.1) # 不加等待0.1秒的话 因为计算机获取结果过快 会一致提示进程是存活状态
print(p.is_alive()) # 判断进程是否存活
print('主进程')
print(p.name)
执行结果:
False
主进程
Process-1
UDP代码编写、操作系统发展史、多道技术、进程理论与代码层面创建、进程join方法与进程对象方法的更多相关文章
- 3、网络并发编程--udp代码、操作系统发展史、多道技术、进程理论
昨日内容回顾 socket基本使用 # 内置的模块 import socket s = socket.socket() # 默认是TCP协议 也可以切换为UDP协议 s.bind((ip,port)) ...
- Python进阶----计算机基础知识(操作系统多道技术),进程概念, 并发概念,并行概念,多进程实现
Python进阶----计算机基础知识(操作系统多道技术),进程概念, 并发概念,并行概念,多进程实现 一丶进程基础知识 什么是程序: 程序就是一堆文件 什么是进程: 进程就是一个正在 ...
- Python3学习之路~9.2 操作系统发展史介绍、进程与线程区别、线程语法、join、守护线程
一 操作系统发展史介绍 参考链接:http://www.cnblogs.com/alex3714/articles/5230609.html 二 进程与线程 进程: 对各种资源管理的集合 就可以称为进 ...
- 基于udp协议的套接字,socketserver模块,多道技术,进程理论
进程指的是一个正在进行/运行的程序,进程是用来描述程序执行过程的虚拟概念 进程vs程序 程序:一堆的代码 进程:程序执行的过程 进程的概念起源于操作系统,进程是操作系统最核心的概念,操作系统的其他所有 ...
- socket之UDP协议,并发编程介绍,操作系统发展史
socket之UDP协议 1.UDP协议 UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection 参考 ...
- tcp\udp 操作系统发展史
目录 为什么会出现粘包现象 socket发送大文件示例 UDP协议 基于UDP实现简易版本的qq 总结: SocketServer模块介绍(让tcp也能支持并发) 为什么会出现粘包现象 TCP 三次握 ...
- UDP协议,多道技术,进程,同步与异步,阻塞与非阻塞
UDP协议 简介 UDP叫做用户数据报协议,是OSI七层参考模型中传输层使用的协议,他提供的是不可靠传输,既它在传输过程 中不保证数据的完整性! 端口号 UDP使用IP地址和端口号进行标识,以此将数据 ...
- 操作系统发展史 & 进程
今日内容 UDP协议 操作系统发展史 进程 单核情况下的进程调度 进程三状态图 同步异步 阻塞非阻塞 内容详细 一.UDP协议 1.什么是UDP协议 UDP是传输层的协议,功能即为在IP的数据报服务之 ...
- UDP协议、操作系统、同步与异步、阻塞与非阻塞
UDP协议 # 客户端 import socket server = socket.socket(type=socket.SOCK_DGRAM) server.bind(('127.0.0.1', 8 ...
随机推荐
- [BUUCTF]REVERSE——[FlareOn4]IgniteMe
[FlareOn4]IgniteMe 附件 步骤: 例行检查,32位程序,无壳 32位ida载入 当满足第10行的if条件时,输出G00d j0b!提示我们成功,看一下sub_401050函数 3.s ...
- bjdctf_2020_babystack2
此题考整型的有符号无符号的东西... 下载文件还是,先检查一下保护. 64位程序,只开启了堆栈不可执行,看一下ida的伪代码. 大概流程就是先让你输入一个数,这个数就是后面read的可以输入的长度,要 ...
- [BUUCTF]PWN20——ciscn_2019_n_5
[BUUCTF]PWN20--ciscn_2019_n_5 附件 步骤: 例行检查,64位,没有开启任何保护 试运行一下程序,看看程序的执行情况 64位ida载入,找到main函数, 逻辑很简单,第一 ...
- YC-Framework版本更新:V1.0.3
分布式微服务框架:YC-Framework版本更新V1.0.3!!! 本次版本V1.0.3更新 集成分布式事务Seata: 集成分布式事务Tx-LCN: 集成Kafka: 集成RocketMQ: 集成 ...
- CF570A Elections 题解
Content 有 \(n\) 个候选人和 \(m\) 个城市,每个城市可以给每个候选人投票,已知第 \(i\) 个城市给第 \(j\) 个人投的选票数是 \(a_{i,j}\).我们将第 \(i\) ...
- SpringBoot整合kafka的简单应用及配置说明
引入依赖 <!-- https://mvnrepository.com/artifact/org.springframework.kafka/spring-kafka --> <de ...
- 【剑指Offer】10- I. 斐波那契数列 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人微信公众号:负雪明烛 目录 题目描述 解题方法 递归 动态规划 日期 题目地址:htt ...
- 【LeetCode】622. Design Circular Queue 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 用直的代替弯的 数组循环利用 日期 题目地址:htt ...
- hdu-5568SUM (dp)
sequence2 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...
- Lucky Substrings
而在26以内且属于fibonacci数列的数为1,2,3,5,8,13,21时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 A string s is LUCKY if ...