网络编程
- UDP协议
- UDP协议实战
- 操作系统的发展史
- 多道技术
- 进程理论
UDP协议
import socket # 导入socket模块
server = socket.socket(type=socket.SOCK_DGRAM) # 自己指定UDP协议(默认是TCP协议)
server.bind(('127.0.0.1', 8080)) # 绑定一个固定的地址(IP与端口号)
msg, addr = server.recvfrom(1024) # 接收客户端返回的
print('msg>>>:', msg.decode('utf8')) # 解码操作
print('addr>>>:', addr) # 打印客户端的地址
server.sendto(b'hello baby', addr) # 回复客户端的消息
import socket # 导入模块
client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080) # 查找通讯录
client.sendto(b'hello server baby', server_addr) # 接收服务端的消息
msg, addr = client.recvfrom(1024)
print('msg>>>:', msg.decode('utf8'))
print('addr>>>:', addr)
UDP协议实操
# 服务端
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080))
while True:
msg, addr = server.recvfrom(1024)
print(addr)
print(msg.decode('utf8'))
back_msg = input('请回复消息>>>:').strip()
server.sendto(back_msg.encode('utf8'), addr)
# 客户端1
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080)
while True:
msg = input('请输入想要聊天的内容>>>:').strip()
msg = '来自客户端1的消息:%s' % msg
client.sendto(msg.encode('utf8'), server_addr)
msg, addr = client.recvfrom(1024)
print(msg.decode('utf8'), addr)
# 客户端2
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080)
while True:
msg = input('请输入想要聊天的内容>>>:').strip()
msg = '来自客户端2的消息:%s' % msg
client.sendto(msg.encode('utf8'), server_addr)
msg, addr = client.recvfrom(1024)
print(msg.decode('utf8'), addr)
由以上可知一个服务端可以处理多个客户端,但是它们两个是按照串行执行,就是一定要等到服务器接收到了客户端1的返回值才会为客户端2提供服务
操作系统的发展史
1.穿孔卡片
优势:一个人独占电脑
劣势:CPU利用率极低
2.联机批处理系统
一次性可以录入多个用户指令、缩短了CPU等待的时间、提高了CPU的利用率
3.脱机批处理系统
是现代计算机核心部件的雏形、提高CPU的利用率
# 总结:操作系统的发展史其实就是提升CPU利用率的过程
多道技术
前提:计算机都是单核(一个CPU)的情况下
串行:多个任务排队执行,总耗时就是多个任务完整时间叠加
多道:利用空闲提前准备,缩短总的执行时间并且还能提高CPU利用率
eg:做饭需要30min
洗衣需要50min
烧水需要20min
串行总共需要耗时:30min + 50min + 20min
多道总共需要耗时:50min
# 多道技术
1.空间上的复用:多个任务公用一套计算机硬件
2.时间上的复用:切换+保存状态
ps:CPU在两种情况下会被拿走
1.程序遇到IO操作,CPU会自动切走运行其它程序
2.程序长时间占用CPU,系统发现之后也会强行切走CPU,保证其它程序也能使用
进程理论
程序:一堆没有被执行的代码(死的)
进程:正在运行的程序(活的)
# 为了更加精确的描述出一些实际状态才有了进程的概念
# 进程调度算法发展史
1.先来先服务
对短作业任务不太友好
2.短作业优先
多长作业任务不太友好
3.时间片轮转法与多级反馈队列
时间片轮转法:先公平的将CPU分给每个人执行
多级反馈队列:根据作业长短的不同再合理分配CPU执行时间
'''目的就是为了能够让单核的计算机也能够做到运行多个程序'''
重要概念
# 并发:看上去像同时在执行就可以称之为是并发(让CPU在多个程序之间利用多道技术来回切换+保存状态)
# 并行:必须同一时间同时运行才可以称之为并行。
ps:单核计算机能够实现并发,但是不能实现并行,想要实现并行就必须要有多个CPU
# 高并发与高并行
高并发:我们写的软件可以支持1个亿的并发量,一个亿的用户来了之后都可以感觉到自己被服务着
高并行:我们写的软件可以支持1个亿的并行量,上述话语的言外之意是计算机有一亿个CPU
# 同步与异步
同步:提交完任务之后原地等待任务的返回结果 期间不做任何事情
异步:提交完任务之后不愿地等待任务的结果 直接去做其他事情 有结果自动提醒
# 阻塞与非阻塞
了解阻塞与非阻塞之前要先搞清楚进程三状态图:
就绪态:程序进入运行状态之前肯定要处于就绪态
运行态:程序被CPU执行着
阻塞态:程序执行过程中有IO操作
阻塞:阻塞态
非阻塞:就绪态、运行态
ps:如果想要尽可能的执行程序执行效率,就要想办法让我们的程序一种处于就绪状和运行状(不要有IO操作)
同步异步与阻塞非阻塞的组合
同步异步:用来描述任务的提交方式
阻塞非阻塞:用来描述任务的执行状态
# 上述两组属于两个不同概念 但是可以结合
同步阻塞:银行排队办理业务 期间不做任何事
同步非阻塞:银行排队办理业务 期间喝水吃东西 但是人还在队列中
异步阻塞:在椅子上坐着 但是不做任何事
异步非阻塞:在椅子上坐着 期间喝水吃东西办公 (程序运行的极致)
作业讲解
编写一个cs架构的软件
就两个功能
一个视频下载:从服务端下载视频
一个视频上传:从客户端上传视频
# 服务端
import socket
import json
import struct
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)
sock, addr = server.accept()
# 1.接收固定长度的报头
header = sock.recv(4)
# 2.解析出字典的长度
dict_len = struct.unpack('i', header)[0]
# 3.接收字典数据
dict_bytes = sock.recv(dict_len)
dict_data = json.loads(dict_bytes)
# 4.接收真实数据
recv_size = 0
total_size = dict_data.get('file_size')
file_name = dict_data.get('file_name')
# 5.文件操作
with open(file_name, 'wb') as f:
while recv_size < total_size:
data = sock.recv(1024)
f.write(data)
recv_size += len(data)
# 客户端
import socket
import os
import json
import struct
client = socket.socket()
client.connect(('127.0.0.1', 8080))
movie_dir_path = r'/Users/jiboyuan/Desktop/直播课/python基础day33/视频'
while True:
# 1.循环展示出需要上传的电影列表
movie_name_list = os.listdir(movie_dir_path)
for i, movie_name in enumerate(movie_name_list, start=1):
print(i, movie_name)
choice = input('请选择您想要上传的电影编号>>>:').strip()
if not choice.isdigit():
continue
choice = int(choice)
if choice not in range(1, len(movie_name_list) + 1):
print('请输入正确的编号')
continue
# 2.获取电影名字
target_movie_name = movie_name_list[choice - 1]
# 3.拼接电影路径
movie_path = os.path.join(movie_dir_path, target_movie_name)
# 4.制作字典数据
movie_dict = {
'file_name': target_movie_name,
'file_desc': '请及时补充营养',
'file_size': os.path.getsize(movie_path)
}
movie_dict_json = json.dumps(movie_dict)
movie_dict_len = len(movie_dict_json.encode('utf8'))
# 5.制作字典报头
dict_header = struct.pack('i', movie_dict_len)
# 6.发送字典报头
client.send(dict_header)
# 7.发送字典数据
client.send(movie_dict_json.encode('utf8'))
# 8.发送真实数据
with open(movie_path,'rb') as f:
for line in f:
client.send(line)