python(黏包处理方法,并发编程理论)

今日内容概要

  • 黏包现象
  • 解决黏包逻辑思路
  • UDP基本代码使用
  • 并发编程理论及操作系统发展史
  • 单道及多道技术
  • 进程理论及调度算法

黏包现象

1.服务端连续执行三次recv
2.客户端连续执行send
问题: 服务端一次性收到了客户端的三次信息  该现象就被称为“黏包现象”

黏包产生的原因
	1.不知道每次接受的数据到底有多大
    2.TCP也称为流式协议:数据就像流水 一样绵绵不绝没有间隔(TCP会根据数据量较小且发送间隔较短的多条数据一次性合并打包发走)

避免/解决思路:
	如何知道数据具体的大小。
 如何将长度变化的数据全部制作成固定的长度的数据

struct模块

能够将数据的大小打包成固定的长度并且还能解析打包之前的大小

struct.pack('i',len(打包的数据))	打包数据  
struct.uppack('i',len(解包数据的长度))	解包数据

解决黏包逻辑思路:

客户端:
	1.制作真实数据的信息字典(数据强度,数据简介,数据名称)
    2.利用struct模块制作字典的报头
    3.发送固定的长度报头(解析出来是字典的长度)
    4.发送字典数据
    5.发送真实数据
    
服务端:
	1.接受固定长度的字典报头
    2.解析出字典的长度并接受
    3.通过字典获取到真实数据的各项信息
    4.接收真实数据长度

image

黏包代码实战:

客户端:
import socket
import os
import struct
import json


client = socket.socket()
client.connect(('127.0.0.1',8080))
"""任何的文件都是下列的思路(图片,文件,文本内容。。。)"""
#1.获取真实数据大小
file_size = os.path.getsize(r'E:\网络编程\xxx合集.txt')
#2.制作真实数据的字典数据
data_dict = {
    'file_name':'python基础习题',
    'file_size':file_size,
    'file_desc':'都是一些学python的入门小知识点',
   ' file_info':'全部都是一些基础的不能在基础的东西'
}
# 3.制作字典报头
data_dit_bytes = json.dumps(data_dict).encode('utf8')
data_dict_len = struct.pack('i',len(data_dit_bytes))
#4.发送字典报头  报头本身也是bytes类型,我们再看的时候用len长度4
client.send(data_dict_len)
# 5.发送字典
client.send(data_dit_bytes)
# 6.最后发送真实数据
with open(r'E:\网络编程\xxx合集.txt','rb')as f:
    for line in f: # 数据一行行发送和一次性发是一样的,因为TCP是流式协议的特性
        client.send(line)

        
服务端:

import socket
import json
import struct


sever = socket.socket()
sever.bind(('127.0.0.1',8080))
sever.listen(5)

sock,addr = sever.accept()
# 1.接收固定长度的字典报头
data_dict_head = sock.recv(4)
# 2.根据报头解析出字典数据的长度
data_dict_len = struct.unpack('i',data_dict_head)[0]
#3.接收字典数据
data_dict_bytes= sock.recv(data_dict_len)
# 自动解码再反序列化
data_dict = json.loads(data_dict_bytes)
# 4.获取真实数据的各项信息(有两种方式)
# 方式一:
total_size = data_dict.get('file_size')
with open(data_dict.get('file_name'),'wb') as f:
    f.write(sock.recv(total_size))

"""
接收真实数据的时候,如果数据量非常大,recv括号内直接填写数据量不太合适,
我们可以每次收一点点,反正知道总长度
"""

# 方式二:
# total_size =data_dict.get('file_size')
# recv_size = 0
# with open(data_dict.get('file_name'),'wb') as f:
#     while recv_size < total_size:
#         data = sock.recv(1024)
#         f.write(data)
#         recv_size+=len(data)
#         print(recv_size)

UDP基本代码使用

1.UDP服务端和客户端都是'各玩各的'
2.UDP不会出现多个消息发送合并

服务端:
import socket
udp_sk = socket.socket(type=socket.SOCK_DGRAM)   #创建一个服务器的套接字
udp_sk.bind(('127.0.0.1',9000))    #绑定服务器套接字
msg,addr = udp_sk.recvfrom(1024)
print(msg)
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)
back_msg,addr=udp_sk.recvfrom(1024)
print(back_msg.decode('utf-8'),addr)

并发编程理论及操作系统发展史

并发编程理论:

并发编程其实就是在研究计算机底层原理的发展史
"计算机中,最重要的就是要明白一点,真正干活的人就是CPU"
除了CPU计算机中操作系统也是不能少的,接下来一了解操作系统的发展史

手工操作———穿孔卡片

1946年第一台计算机诞生--20世纪50年代中期,计算机工作还在采用手工操作方式。此时还没有操作系统的概念。想要通过计算机来执行自己想要它执行的指令需要 程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入输入机,然后启动输入机把程序和数据输入计算机内存,接着通过控制台开关启动程序针对数据运行;计算完毕,打印机输出计算结果;用户取走结果并卸下纸带(或卡片)后,才让下一个用户上机。
  • 手工操作方式两个特点:

      (1)优点:用户独占全机。不会出现因资源已被其他用户占用而等待的现象,但资源的利用率低。

      (2)缺点:CPU 等待手工操作。CPU的利用不充分,浪费资源。

批处理————磁带存储

 批处理系统:加载在计算机上的一个系统软件,在它的控制下,计算机能够自动地、成批地处理一个或多个用户的作业(这作业包括程序、数据和命令)

  • 联机批处理系统
    提前使用磁带一次性录入多个程序员编写的程序 然后交给计算机执行(就是输入/输出)
    CPU工作效率有所提升 不用反复等待程序录入

  • 脱机批处理系统

    ​ 其功能是:

      (1)从输入机上读取用户作业并放到输入磁带上。

      (2)从输出磁带上读取执行结果并传给输出机。

      			极大地提升了CPU的利用率
    

    总结:所做的一切改进就是为了将CPU提升利用率的过程

单道及多道技术

概念:多道程序系统就是为了提高CPU的利用率

单道程序计数设计

就是所有的程序拍着队的执行,在此过程中不能重合
分析:外设和CPU交替空闲和忙碌,CPU和外设利用效率低

缺点:
从单道批处理系统对CPU的利用情况可看出,作业运行过程中若发生IO请求,高速的CPU要等待低速的I/O操作完成,导致CPU资源利用率和系统吞吐量降低。

image

多道批处理系统

利用空闲提前准备 缩短总的执行时间并且还能提高CPU利	
    
    多道程序设计技术不仅使CPU得到充分利用,同时改善I/O设备和内存的利用率,从而提高了整个系统的资源利用率和系统吞吐量(单位时间内处理作业(程序)的个数),最终提高了整个系统的效率。
单处理机系统中多道程序运行时的特点:
  (1)多道:计算机内存中同时存放几道相互独立的程序;
  (2)宏观上并行:同时进入系统的几道程序都处于运行过程中,即它们先后开始了各自的运行,但都未运行完毕;
  (3)微观上串行:实际上,各道程序轮流地用CPU,并交替运行。
    
  """
多道技术
	1.空间上的复用
		多个任务共用一套计算机硬件
	2.时间上的复用
		切换+保存状态
		CPU在两种情况下会被拿走
			1.程序遇到IO操作 CPU自动切走运行其他程序
			2.程序长时间占用CPU 系统发现之后也会强行切走CPU 保证其他程序也可以使用
"""

image

进程理论及调度算法

进程理论:

什么是进程?

其实进程一直都贯穿着我们的周围,无论是我们使用的智能手机还是电脑,其实都与进程息息相关。比如我们打开某短视频软件,其实就是打开该短视频的一个进程。我们甚至可以说进程就是一个软件的本身,再专业一些的话就是 进程就是程序执行的载体

对于操作系统来说一个任务就是一个进程,比如打开一个APP就是启动一个APP进程,打开一个浏览器就是启动一个浏览器进程。

总结:进程就是正在执行的程序代码(动起来)
	程序就是一堆没有执行的代码(没有动起来)

进程的特征:
1.动态性,是进程最基本的特性,可表现为由创建而产生,由调度而执行,因得不到资源而暂停执行,以及由撤销而消亡,因而进程由一定的生命期。

2.并发性,是进程的重要特征,同时也是OS的重要特征。引入进程的目的正是为了使其程序能和其它建立了进程的程序并发执行。

3.独立性,是指进程实体是一个能独立运行的基本单位,同时也是系统中独立获得资源和独立调度的基本单位。

进程的调度算法(重要):

1.FCFC(先来先服务)
对于短作业不友好
2.短作业优先调度
对于长作业不友好
3.时间片轮转法+多级反馈队列(目前还在用)
时间片轮转法:先公平的将CPU分给每个人执行
多级反馈队列:根据作业长短的不同再合理分配CPU执行时间
等级越靠下就表示需要耗时的时长就越多,但是优先级就越低
  '''目的就是为了能够让单核的计算机也能够做到运行多个程序'''

image

进程的并行与并发:

并行:是指多个进程同时执行,必须要有多个CPU参与),单个CPU是无法实现并行的(必须是同一时间运行才可以称之为并行

并发:是指多个进程看上去像是同一时刻执行,单个CPU可以实现,多个CPU也可以

	并发相比并行,处理方式不同,并发是一个处理器同时处理多个任务,并行是多个处理器同时处理多个任务,并发是逻辑同时,并行是物理同时。

	并发相比并行,在宏微观上由于处理器的利用方式不同,并发同时轮换多个进程,宏观上保持了进程同时进行,而并行不论宏观微观都是真正的同时进行。

	并发执行的特点是使得多个进程在逻辑上同时执行,将多个进程的指令轮换执行,表现为多个进程的执行挂起再执行,在宏观上似乎是同时执行了多个进程。

	并发执行类似于时分复用的特点,将CPU处理器进行不同时间利用,达到同时执行多个进程的目的

进程的三种状态:

1 .就绪状态:进程已获得除CPU外的所有必要资源,只等待CPU时的状态。系统会将多个处于就绪状态的进程排成就绪队列。

2.执行状态:进程已获CPU,正在执行。单处理机系统中,处于执行状态的进程只一个;多处理系统中,有多个处于执行状态的进程。

3.阻塞状态:正在执行的进程由于某种原因而暂时无法继续执行,便放弃处理机而处于暂停状态,即进程执行受阻。(这种状态又称等待状态或封锁状态)
image

# 高并发与高并行
	高并发:我们写的软件可以支持1个亿的并发量
    	一个亿的用户来了之后都可以感觉到自己被服务着
  高并行:我们写的软件可以支持1个亿的并行量
    	上述话语的言外之意是计算机有一亿个CPU
posted @ 2022-11-17 20:38  亓官扶苏  阅读(232)  评论(0)    收藏  举报