python学习day32 黏包 struct模块

为什么会出现黏包问题? 

首先只有在TCP协议中才会出现黏包现象

是因为TCP协议是面向流的协议

在发送的数据 传输过程中 有缓存机制 来避免数据丢失

因此 在连续发送小数据的时候 以及接收大小不符的时候都容易出现黏包现象

本质还是因为我们在接受数据的时候不知道发送的数据的长短

怎么解决黏包问题?

在接收端发送要发送的数据的大小

一种是不带struct  一种是带struct  定制协议

 

黏包

http://www.cnblogs.com/Eva-J/articles/8244551.html#_label5

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

黏包成因:

多个send可能会发生黏包现象

优化算法不优化

发生黏包两种现象:

情况一 发送方的缓存机制

发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)

情况二 接收方的缓存机制

接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)

 

 如何解决黏包?

存在的问题:
多了一次交互。程序的运行速度远快于网络传输速度,所以在发送一段字节前,先用send去发送该字节流长度,这种方式会放大网络延迟带来的性能损耗

struct模块

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

这个模块可以把要发送的数据长度转换成固定长度的字节。这样客户端每次接收消息之前只要先接受这个固定长度字节的内容看一看接下来要接收的信息大小,那么最终接受的数据只要达到这个值就停止,就能刚好不多不少的接收完整的数据了。

 

import structret = struct.pack('i', 2049)  # pack方法,将对象转换成固定字节长度bytes类型

num = struct.unpack('i', ret)  # 解包
print(num)   # 元组
print(num[0])  # 数字

 

 

连续send  连续receive

 

我们在网络上传输的所有数据,都叫数据包

数据包中的数据,都叫报文

报文里不只有你的数据 ip地址 mac地址 端口号

所有的报文都有报头  相当于协议 接收多少字节 什么顺序 等等

报头可以自己定制

根据报头来解包接收的数据

  复杂的应用上就会用到定制报头

    比如:传输文件的时候

      文件名、大小、类型、路径

 

网络传输中,处处有有协议,协议就是一堆报文和报头 ———字节

协议的解析过程我们不需要关心

我们也可以自定制协议

 

 实现一个大文件的上传或下载:

客户端作发送端:

import socket
import os
import json
import structsk = socket.socket()
sk.connect(('127.0.0.1',8090))# 发文件
# 定制报头
head = {'filepath':r'H:\python\day32','filename':r'05 python fullstack s9day32 strcuct模块定制报头的理论.mp4','filesize':None}
file_path = os.path.join(head['filepath'],head['filename'])
file_size = os.path.getsize(filepath)
head['filesize'] = file_sizejson_head = json.dumps(head)  # 字典转成字符串
bytes_head = json_head.encode('utf-8') # 字符串转bytes类型
head_len = len(bytes_head)  # 报头的长度
pack_len = struct.pack('i', head_len)  # 报头长度转成固定的4字节长度

sk.send(pack_len)  # 先发报头长度
sk.send(bytes_head)  # 再发报头内容
# 然后再发文件内容:
buffer = 1024
with open(filepath, 'rb') as f:while file_size:if file_size >= buffer:content = f.read(buffer)sk.send(content)file_size -= bufferelse:content = f.read(file_size)sk.send(content)break
sk.close

服务端:

import socket
import os
import json
import structsk = socket.socket()
sk.bind(('127.0.0.1',8090))
sk.listen()conn, addr = sk.accept()
# 接收
head_len = conn.recv(4)  # 接收报头长度
head_len = struct.unpack('i', head_len)[0]  # 解包成元组 第一个
json_head = conn.recv(head_len).decode('utf-8')
head = json.loads(json_head)   # 报头

filesize = head['filesize']
buffer = 1024
# 写入文件
with open(head['filename'], 'wb') as f:while filesize:if filesize >= buffer:content = conn.recv(buffer)f.write(content)filesize -= bufferelse:f.write(conn.recv(filesize))breakconn.close
sk.close

 

转载于:https://www.cnblogs.com/happyfan/p/10450905.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/425545.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HDU-5935 Car 逆推 贪心 精度

题意 1 主人公从0开始开始跑 2 使用速度非递减技能 3 警察记录下了多个整数时间点他的位置 整数时间点不明确 让我们求主人公所花费的最小时间跨越过最后一个位置点 分析 本体选用逆推处理 为啥用逆推 因为速度是非递减的 如果从前面推 会导致不断重复修改 前面的时间 时间不…

[Leedcode][JAVA][第1300题][转变数组后最接近目标值的数组和][前缀和][二分法][暴力]

【问题描述】[中等] 给你一个整数数组 arr 和一个目标值 target ,请你返回一个整数 value ,使得将数组中所有大于 value 的值变成 value 后,数组的和最接近 target (最接近表示两者之差的绝对值最小)。如果有多种使得…

线性系统的基本理论与运算

线性系统的基本理论与运算 线性系统与非线性系统 线性系统的基本理论 二维线性移不变系统 线性移不变系统 如果一个系统既是线性系统,又是移不变系统,则该系 统是线性移不变系统。

行云管家堡垒机 导入腾讯云主机

行云管家堡垒机 导入腾讯云主机 如何实现了对多家云厂商多种云计算资源的集中管理,从成本、监控、备份、安全等多个维度提供统一运维管控? 工具/原料 行云管家堡垒机方法/步骤 Step1:注册登录 登录行云管家,支持QQ、微信、微博、G…

HDU - 5438 Ponds 拓扑 dfs

题意 在一个图中 给出了每个点得权值和连边 想要尽可能删除一些联通的点数小于2的点 删完后 求最后剩下联通块内点得数量是奇数的权值和 分析 本题由于在删除点得过程中需要考虑 当把当前点删除后 其联通的点也有可能会因为当前点得删除而连边小于2同时删除 考虑拓扑排序 建…

(总结)HTTP常见错误返回代码

(总结)HTTP常见错误返回代码 HTTP返回状态代码 当用户试图通过HTTP或FTP协议访问一台运行主机上的内容时,Web服务器返回一个表示该请求的状态的数字代码。该状态代码记录在服务器日志中,同时也可能在 Web 浏览器或 FTP客户端显示…

MyBatis面试题(2020最新版)

目录MyBatis简介MyBatis是什么?ORM是什么为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?传统JDBC开发存在的问题JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的?Mybatis优缺点MyBatis框架适用场景…

Java学习笔记9-2——JavaWeb

文章目录JavaBeanMVC三层架构Filter过滤器Listener监听器JDBC文件上传Servlet邮件发送ServletJavaBean 实体类 JavaBean有特定的写法: 必须要有一个无参构造;属性必须私有化;必须有对应的get/set方法; 一般用来和数据库的字段…

linux日常常用命令分析

日志处理:测试网络路由: xargs使用方法:tcpdump命令分析:dd 写入磁盘测试cpu个数:查看网卡流量查看端口联通情况,临时加端口ntpdate同步:可以取出变动的密码:导堆栈:根据进程id查看程…

离散傅立叶变换

离散傅立叶变换 一维离散傅里叶变换 二维离散傅里叶变换(2D-DFT) 、图像傅里叶变换的意义 (1)简化计算,也即傅里叶变换可将空间域中复杂的卷 积运算转化为频率域中简单的乘积运算。 (2)对于某些在空间域中难于处理或…

[Leedcode][JAVA][第14题][最长公共前缀][二分][横竖扫描][分治]

【问题描述】[中等] 编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""。示例 1:输入: ["flower","flow","flight"] 输出: "fl" 示例 2:输入: ["dog","raceca…

【模板】在build中配置resources来防止我们资源导出失败的问题

在build中配置resources&#xff0c;来防止我们资源导出失败的问题 <!--在build中配置resources&#xff0c;来防止我们资源导出失败的问题--><build><resources><resource><directory>src/main/resources</directory><includes><…

JDBC_设计架构_驱动类加载_建立Connection_效率测试

JDBC(Java DataBase Connection) 访问数据库流程&#xff1a;驱动管理器--连接数据库--sql语句--结果集 装载mysql驱动 Class.forName("com.jdbc.mysql.Driver"); DriverManager接口是JDBC的管理器&#xff0c;作用于用户和驱动程序之间。 Demo1.java package com.qh…

HDU-4793 Collision 计算几何 解方程

题意 给我们两个大小不同的圆的半径小圆是实心的 大圆是空心的 然后给我们一个小球的半径 小球的初始位置 还有飞碟在x方向和y方向上的速度 小球撞到内实心圆会能量不损失的反弹 问小球任何位置与大圆相交到完全出去的时间是多少 分析 几何题 如何知道时间呢 如果小球与大圆…

图像傅里叶变换频谱分析

图像的傅里叶频谱特性分析 图像傅里叶频谱关于(/&#xff0c;/)的对称性 图像傅里叶频谱特性及其频谱图 傅里叶变换在图像处理中的应用

[剑指offer]面试题第[37]题[Leedcode][JAVA][第297题][二叉树列的序列化与反序列化][递归][BFS]

【问题描述】[中等] 序列化是将一个数据结构或者对象转换为连续的比特位的操作&#xff0c;进而可以将转换后的数据存储在一个文件或者内存中&#xff0c;同时也可以通过网络传输到另一个计算机环境&#xff0c;采取相反方式重构得到原数据。请设计一个算法来实现二叉树的序列…

Java学习笔记10-1——MyBatis

文章目录简介第一个Mybatis程序搭建环境导入Mybatis&#xff0c;编写配置文件编写代码测试了解一下官方文档的建议实现增删改查select、insert、update、delete使用map进行CRUD模糊查询配置解析(mybatis-config.xml)核心配置文件mybatis-config.xml环境配置&#xff08;environ…

时间

//Step1: 定义任务函数: 计算当前时间距离target时间的时间差var targetnew Date("2019/3/01 18:00:00");function calc(){//获得当前系统时间保存在变量now中var nownew Date();//用target-now&#xff0c;再除1000&#xff0c;获得秒差&#xff0c;保存在变量s中va…

图像的离散余弦变换

Discrete Cosine Transform&#xff0c;简写为DCT 函数的偶对称性使DCT只有实数域变换结果, 不再涉及复数运算&#xff0c;运算简单&#xff0c;费时少&#xff1b; 又保持了变换域的频率特性&#xff1b; 与人类视觉系统特性相适应&#xff1b; 得到了更加广泛的应用。 二维…

【匈牙利算法】【二分图匹配】【转载】趣写算法系列之--匈牙利算法

转载自&#xff1a;http://blog.csdn.net/dark_scope/article/details/8880547 【书本上的算法往往讲得非常复杂&#xff0c;我和我的朋友计划用一些简单通俗的例子来描述算法的流程】 匈牙利算法是由匈牙利数学家Edmonds于1965年提出&#xff0c;因而得名。匈牙利算法是基于H…