粘包现象

1.服务端连续执行三次recv

2.客户端连续执行三次send

问题:服务端一次性接收到了客户端三次的消息 该现象称为 粘包现象

粘包现象产生的原因:

​ 1.不知道每次的数据到底有多大

​ 2.TCP也称为流式协议:数据像流水一样绵绵不绝没有间隔(TCP会针对数据量较小且发送间隔较短的多条数据一次性打包发送)

注意:只有TCP有粘包现象,UDP永远不会粘包

避免粘包现象的核心思路\关键点:

​ 如何明确即将接收的数据具体有多大

PS:如何将长度变化的数据全部制作成固定长度的数据

struct模块

该模块可以把一个类型 如数字 转成固定长度的bytes

import struct

msg = b'hello jason brother'
print(len(msg)) # 真实长度19
res = struct.pack('i', len(msg)) # 将数据打包成固定的长度 i是固定打包长度
print(res)
print(len(res)) # 打包后长度为(bytes) 4 报头 real_len = struct.unpack('i', res)
print(real_len) # (19,)元组的形式 根据固定长度解析出真实数据的长度 desc = b'what is wrong with you'
print(len(desc)) # 数据真实的长度(bytes) 22
res1 = struct.pack('i', len(desc))
print(len(res1)) # 打包之后长度为(bytes) 4 报头 real_len1 = struct.unpack('i', res1)
print(real_len1) # (22,) 根据固定长度的报头 解析出真实数据的长度

借助struct模块 知道长度数字可以被转换成一个标准大小的4字节数字 利用这个特点预先发送数据长度

发送时 接收时
先发送struct转换好的数据长度4字节 先接受4个字节使用struct转换成数字来获取要接受的数据长度
再发送数据 再按照长度接收数据

还可以把报头做成字典 字典里包含将要发送的真实数据的详细信息 然后json序列化 然后struct将序列化后的数据长度打包成4个字节

发送时 接收时
先发报头长度 先收报头长度 用struct取出来
再编码报头内容然后发送 根据取出的长度收取报头内容 然后解码 反序列化
最后发真实内容 从反序列化的结果中取出待取数据的详细信息 然后去取真实的数据内容
解决粘包问题初次版本

客户端

​ 1.将真实数据转成bytes类型并计算长度

​ 2.利用struct,模块将真实长度制作一个固定长度的报头

​ 3.将固定长度的报头先发送给服务端 服务端只需要在recv括号内填写固定的长度的报头数据即可

​ 4.然后再发送真实的数据

服务端

​ 1.服务端先接受固定长度的报头

​ 2.利用struct模块反向解析出真实数据长度

​ 3.recv接收真实数据长度即可

问题1:struct模块无法打开数据量较大的数据 就算换更大的模式也不行

res = struct.pack('i', 12313213123)
print(res) # 报错超范围struct.error: argument out of range
struct.error: 'i' format requires -2147483648 <= number <= 2147483647 # 这个是范围

问题2:报头能否传递更多的信息 比如电影大小 电影名称 电影评价电影简介

终极解决方案:字典作为报头打包 效果更好 数字更小

import struct
data_dict = {
'name': 'jason老师教学视频集合',
'size': 131414141423342523543566,
'reaL-info': '手把手教你学 千万不要错过',
'desc': '经典教学视屏'
}
import json
data_json = json.dumps(data_dict)
rang = len(data_json.encode('utf8'))
print(rang) # 237
res = struct.pack('i', rang)
print(len(res)) # 4

粘包问题终极解决方案

客户端

​ 1.制作真实数据的信息字典(数据长度、数据简介、数据名称)

​ 2.利用sturct模块制作字典的报头

​ 3.发送固定长度的报头(解析出来的是字典的长度)

​ 4.发送字典数据

​ 5.发送真实数据

服务端

​ 1.接收固定长度的字典报头

​ 2.解析出字典的长度并接收

​ 3.通过字典获取真实数据的各项消息

​ 4.接收真实数据长度

粘包代码实战

import socket
import struct
import json server = socket.socket()
server.bind(('127.0.0.1', 8081))
server.listen(5) sock, addr = server.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) import socket
import os
import struct
import json client = socket.socket()
client.connect(('127.0.0.1', 8081)) '''任何文件都是下列思路 图片 视频 文本 ...'''
# 1.获取真实数据大小
file_size = os.path.getsize(r'/Users/jiboyuan/PycharmProjects/day36/xx老师合集.txt')
# 2.制作真实数据的字典数据
data_dict = {
'file_name': '有你好看.txt',
'file_size': file_size,
'file_desc': '内容很长 准备好吃喝 我觉得营养快线挺好喝',
'file_info': '这是我的私人珍藏'
}
# 3.制作字典报头
data_dict_bytes = json.dumps(data_dict).encode('utf8')
data_dict_len = struct.pack('i', len(data_dict_bytes))
# 4.发送字典报头
client.send(data_dict_len) # 报头本身也是bytes类型 我们在看的时候用len长度是4
# 5.发送字典
client.send(data_dict_bytes)
# 6.最后发送真实数据
with open(r'/Users/jiboyuan/PycharmProjects/day36/xx老师合集.txt', 'rb') as f:
for line in f: # 一行行发送 和直接一起发效果一样 因为TCP流式协议的特性
client.send(line)
import time
time.sleep(10)

udp协议(了解)

1.UDP服务端和客户端 各自玩各自的

2.UDP不会出现多个消息发送合并

并发编程理论

研究网络编程其实就是在研究计算机的底层原理及发展史

计算机中真正干活的是CPU

操作系统发展史

​ 1.穿孔卡阶段

​ 计算机很庞大 使用很麻烦 一次只能给一个人使用期间很多时候计算机都不工作

​ 好处:程序员独占计算机 为所欲为

​ 坏处:计算机利用率太低 浪费资源

​ 2.联机批处理系统

​ 提前使用磁带一次性录入多个程序员编写的程序 然后交给计算机执行

​ CPU工作效率有所提升 不用反复等待程序录入

​ 3.脱机批处理系统

​ 极大提升了CPU的利用率

​ 总结:CUP提升利用率的过程

多道技术

在学习并发编程的过程中 不做刻意的提醒的情况下 默认一台计算机就一个CPU(只有一个干活的人)

单道技术

​	所有的程序排队执行 过程中不能重合

多道技术

​	利用空闲时间提前准备其他数量 最大化提升CPU利用率

多道技术详细

​	1.切换

​	计算机的CPU在两种情况下会切换(不让你用 给别人用)

​		1.程序有IO操作 输入\输出操作 input 、time.sleep、read、write

​		2.程序运行长时间占用CUP 我们得雨露均沾 让多个程序都能被CPU运行一下

​	2.保存状态

​	CPU每次切换走之前都需要保存当前操作的状态 下次切换回来的时候基于上次的进度继续执行
'''
就好比开了一家饭店 只有一个服务员 但是同时来了五桌客人 如何让五桌客人都感受到服务员在在服务他们 让服务化身为闪电侠 只要客人有停顿 就立刻切换到其他桌 如此往复
'''

进程理论

进程与程序的区别
程序:一堆死代码(还没有被运行起来)
进程:正在运行的程序(被运行起来了)
进程的调度算法(重要)
1.FCFS(先来先服务) 对短作业不友好
2.短作业优先调度 对长作业不友好
3.时间片轮转法+多级反馈队列(目前还在用)
将时间均分 然后根据进程时间长短再分多个等级
等级越靠下表示耗时越长 每次分到的时间越多 但是优先级越低

进程并行与并发

并行:多个进程同时执行 必须要有多个参与 单个CPU无法实现
并发:多个进程看上去像同时执行 单个CPU可以实现 多个CPU肯定也可以实现 判断下列两句话孰对孰错
我写的代码很牛逼 运行起来之后可以实现14个亿的并行量 肯定错的
并行量必须要有对等的CPU才可以实现 我写的程序很牛逼 运行起来之后可以实现14个亿的并发量 对的
合情合理 完全可以实现 以后我们的项目一般都会追求高并发
PS:目前国内可以说是最牛逼的>>>12306

进程的三状态

就绪状态:
所有的进程在被CPU执行之前都必须先进入就绪态等待
运行状态:
CPU正在执行
阻塞态:
进程运行过程中出现了IO操作 阻塞无法直接进入运行态 需要先进入就绪态

粘包、struct模块、进程并行与并发的更多相关文章

  1. Learn day9 粘包\struct用法\hashlib校验\socketserver并发\模块引入\进程\join\守护进程

    1.粘包现象 总结 : 导致黏包现象的两种情况 hello,worl d (1) 在发送端,发送数据太快,频繁发送 (2) 在接收端,接收数据太慢,延迟截取 # ### 服务端 import sock ...

  2. python网络编程基础(线程与进程、并行与并发、同步与异步、阻塞与非阻塞、CPU密集型与IO密集型)

    python网络编程基础(线程与进程.并行与并发.同步与异步.阻塞与非阻塞.CPU密集型与IO密集型) 目录 线程与进程 并行与并发 同步与异步 阻塞与非阻塞 CPU密集型与IO密集型 线程与进程 进 ...

  3. 黏包-黏包的成因、解决方式及struct模块初识、文件的上传和下载

    黏包: 同时执行多条命令之后,得到的结果很可能只有一部分,在执行其他命令的时候又接收到之前执行的另外一部分结果,这种显现就是黏包. 只有TCP协议中才会产生黏包,UDP协议中不会有黏包(udp协议中数 ...

  4. 通过开启子进程的方式实现套接字服务端可以并发的处理多个链接以及通讯循环(用到了subprocess模块,解决粘包问题)

    今日作业:通过开启子进程的方式实现套接字服务端可以并发的处理多个链接以及通讯循环(用到了subprocess模块,解决粘包问题) server(服务端) import socket from mult ...

  5. Python网络编程(2)-粘包现象及socketserver模块实现TCP并发

    1. 基于Tcp的远程调用命令实现 很多人应该都使用过Xshell工具,这是一个远程连接工具,通过上面的知识,就可以模拟出Xshell远程连接服务器并调用命令的功能. Tcp服务端代码如下: impo ...

  6. 解决socket粘包的两种low版模式 os.popen()和struct模块

    os.popen()模式 server端 import socket import os phone = socket.socket() # 实例化一个socket对象 phone.bind((&qu ...

  7. Py-解决粘包现象,tcp实现并发,tcp实现传输文件的程序,校验思路,线程与进程

    黏包现象 TCP粘包就是指发送方发送的若干包数据到达接收方时粘成了一包,从接收缓冲区来看,后一包数据的头紧接着前一包数据的尾,出现粘包的原因是多方面的,可能是来自发送方,也可能是来自接收方TCP接收到 ...

  8. 2、粘包现象(struct模块)

    昨天我们所做的套接字是有漏洞的,它会出现粘包现象,没有发现这个问题的我们今天会进行演示.今天也会稍微讲解一下基于udp的套接字. 一.基于udp的套接字 udp是无链接的,先启动哪一端都不会报错 ud ...

  9. 29、粘包现象(struct模块)

    昨天我们所做的套接字是有漏洞的,它会出现粘包现象,没有发现这个问题的我们今天会进行演示.今天也会稍微讲解一下基于udp的套接字. 本篇导航: 基于udp的套接字 粘包现象 粘包 解决粘包方法 stru ...

  10. {Python之进程} 背景知识 什么是进程 进程调度 并发与并行 同步\异步\阻塞\非阻塞 进程的创建与结束 multiprocess模块 进程池和mutiprocess.Poll

    Python之进程 进程 本节目录 一 背景知识 二 什么是进程 三 进程调度 四 并发与并行 五 同步\异步\阻塞\非阻塞 六 进程的创建与结束 七 multiprocess模块 八 进程池和mut ...

随机推荐

  1. WPF开发经验-WPF的TextBox控件的MouseDown事件不响应的解决方法

    一 问题的发现 最近项目有个需求,大概是,当点击某个TextBox时,先执行一些业务上的逻辑处理. 于是按以往思维,将TextBox的MouseDown事件关联事件处理方法,将业务处理写在方法里. 调 ...

  2. Android类加载流程

    背景 由于前前前阵子写了个壳,得去了解类的加载流程,当时记了一些潦草的笔记.这几天把这些东西简单梳理了一下,本文分析的代码基于Android8.1.0源码. 流程分析 从loadClass开始,我们来 ...

  3. HDU3001 Travelling (状压DP)

    题目没有起点限制,且每个节点至少访问1次,最多访问2次,所以用三进制数表示节点的状态(选取情况). 因为三进制数的每一位是0或1或2,所以预处理z状态S的第j位的数是有必要的. 边界条件:dp[tri ...

  4. BZOJ2654 tree (wqs二分)

    题目描述 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解.   一个最小生成树问题,但是我们要选need条白边,我们用g(i)表示选取i条 ...

  5. 洛谷P2168 [NOI2015] 荷马史诗 (哈夫曼树)

    学了哈夫曼树这道题还是好想的,基本上和构造哈夫曼树的思路一样,但是题目要求最长si的最小值,所以用两个关键字的堆,第一关键字是把出现次数作为权值,第二关键字表示从该节点开始的最长长度,权值相同时,选择 ...

  6. Podman容器基础(二)

    Podman容器技术基础(二) 目录 Podman容器技术基础(二) 容器的使用 用户操作 用户配置文件 容器卷 容器的使用 运行一个容器 [root@cent1 ~]# podman pull ht ...

  7. 「JOISC 2022 Day1」京都观光 题解

    Solution 考虑从\((x_1,y_1)\)走到\((x_2,y_2)\)满足只改变一次方向,则容易求出先向南走当且仅当 \[\frac{a_{x_1} - a_{x_2}}{x_1 - x_2 ...

  8. 聊一聊被 .NET程序员 遗忘的 COM 组件

    一:背景 1.讲故事 最近遇到了好几起和 COM 相关的Dump,由于对 COM 整体运作不是很了解,所以分析此类dump还是比较头疼的,比如下面这个经典的 COM 调用栈. 0:044> ~~ ...

  9. JUC(4)Callable和常用的辅助类

    1.Callable 1.可以有返回值 2.可以抛出异常 3.方法不同.run()/call() future Task 细节: 1.有缓存 2.结果可能需要等待,会阻塞 2.常用的辅助类 2.1 C ...

  10. 齐博x2模型里边钩子的创建与使用

    在模型里边的钩子创建与使用方法跟在控制器里边的钩子创建及使用方法是有所区别的在模型里边创建的钩子,你可以理解为执行一个函数,是无法调用模型里边的类的方法及属性的.比如系统文件\application\ ...