python 用struct模块解决黏包问题


Posted in Python onNovember 07, 2020

为什么会出现黏包现象:

首先只有在TCP协议中才会出现黏包现象,是因为TCP协议是面向流的协议,在发送的数据传输的过程中还有缓存机制来避免数据丢失,因此,在连续发送小数据的时候,以及接收大小不符的时候容易出现黏包现象。本质还是因为我们在接收数据的时候不知道发送的数据的长短。

解决黏包问题

在传输大量数据之前首先告诉接收端要发送的数据大小,如果想更漂亮的解决问题,可以通过struct模块来定制协议。

struct模块:

功能:可以把一个类型,如数字,转成固定长度的bytes。

import struct

ret = struct.pack('i',456872783)   #'i'代表int,就是即将要把一共数字转换成固定长度(4个字节)的bystes类型
print(ret)

num = struct.unpack('i',ret)  #转换回来,返回一个元组
print(num[0])  #提前元组中的值得到4096

解决黏包问题:

服务端:

import struct
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn,addr = sk.accept()
while True:
  cmd = input('>>>')
  if cmd == 'q':   #当输入‘q'时,结束,并向客户端发送一个'q'。
    conn.send(b'q')
    break
  conn.send(cmd.encode('gbk'))  #将输入的cmd命令发送给客户端
  num = conn.recv(4)   #接收字节信息(返回的消息长度信息)。
  num = struct.unpack('i',num)[0]   #将接收的字节码转化为原来的类型并放在一个元组里面,后面加[0]是提前出元组中的值。
  res = conn.recv(int(num)).decode('gbk')   #接收长度为num 的消息。
  print(res)   #打印
conn.close()
sk.close()

客户端:

import struct
import socket
import subprocess

sk = socket.socket()
sk.connect(('127.0.0.1',8080))
while True:
  cmd = sk.recv(1024).decode('gbk')  #接收服务端发送来的cmd命令
  if cmd == 'q': #当接收到‘q'时,结束。
    break
  # 在客户端执行接收到的cmd命令。并将正确的消息和错误的消息分别放入stdout和stderr管道。
  res = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
  std_out = res.stdout.read()   #读取管道内正确的消息
  std_err = res.stderr.read()   #读取管道内错误的消息
  len_num = len(std_out)+len(std_err)   #计算正确和错误消息的总长度
  num_by = struct.pack('i',len_num)    #将消息总长度转换成长度为4的字节码
  sk.send(num_by)   #发送消息长度信息
  sk.send(std_out)  #发送正确消息
  sk.send(std_err)   #发送错误消息

sk.close()

以上就是python 用struct模块解决黏包问题的详细内容,更多关于python struct模块的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python fileinput模块使用实例
Jun 03 Python
对python读取zip压缩文件里面的csv数据实例详解
Feb 08 Python
Python 2/3下处理cjk编码的zip文件的方法
Apr 26 Python
Scrapy-Redis结合POST请求获取数据的方法示例
May 07 Python
python 中pyqt5 树节点点击实现多窗口切换问题
Jul 04 Python
Django Aggregation聚合使用方法解析
Aug 01 Python
python 提取文件指定列的方法示例
Aug 07 Python
python 穷举指定长度的密码例子
Apr 02 Python
pycharm专业版远程登录服务器的详细教程
Sep 15 Python
如何在scrapy中集成selenium爬取网页的方法
Nov 18 Python
python实现学生信息管理系统(精简版)
Nov 27 Python
OpenCV全景图像拼接的实现示例
Jun 05 Python
python hmac模块验证客户端的合法性
Nov 07 #Python
python如何利用paramiko执行服务器命令
Nov 07 #Python
基于python模拟TCP3次握手连接及发送数据
Nov 06 #Python
如何使用Django Admin管理后台导入CSV
Nov 06 #Python
Selenium结合BeautifulSoup4编写简单的python爬虫
Nov 06 #Python
python两种获取剪贴板内容的方法
Nov 06 #Python
用python写一个带有gui界面的密码生成器
Nov 06 #Python
You might like
php 常用类整理
2009/12/23 PHP
PHP下利用shell后台运行PHP脚本,并获取该脚本的Process ID的代码
2011/09/19 PHP
PDO版本问题 Invalid parameter number: no parameters were bound
2013/01/06 PHP
Linux环境下搭建php开发环境的操作步骤
2013/06/17 PHP
PHP Oauth授权和本地加密实现方法
2016/08/12 PHP
php依赖注入知识点详解
2019/09/23 PHP
如何在PHP环境中使用ProtoBuf数据格式
2020/06/19 PHP
javascript中的location用法简单介绍
2007/03/07 Javascript
JavaScript数值数组排序示例分享
2014/05/27 Javascript
javascript删除元素节点removeChild()用法实例
2015/05/26 Javascript
js实现数组转换成json
2015/06/26 Javascript
Node.js环境下JavaScript实现单链表与双链表结构
2016/06/12 Javascript
nodejs中实现用户注册路由功能
2019/05/20 NodeJs
VUE写一个简单的表格实例
2019/08/06 Javascript
vue+element树组件 实现树懒加载的过程详解
2019/10/21 Javascript
vue项目初始化到登录login页面的示例
2019/10/31 Javascript
jquery实现直播弹幕效果
2019/11/28 jQuery
JavaScript 实现下雪特效的示例代码
2020/09/09 Javascript
jquery自定义组件实例详解
2020/12/31 jQuery
在Python中操作时间之tzset()方法的使用教程
2015/05/22 Python
Python使用flask框架操作sqlite3的两种方式
2018/01/31 Python
python统计中文字符数量的两种方法
2019/01/31 Python
python pyinstaller打包exe报错的解决方法
2019/11/02 Python
Pytorch Tensor的统计属性实例讲解
2019/12/30 Python
python通过matplotlib生成复合饼图
2020/02/06 Python
pycharm实现在子类中添加一个父类没有的属性
2020/03/12 Python
CSS中垂直居中的简单实现方法
2015/07/06 HTML / CSS
CSS3实现多背景模拟动态边框的效果
2016/11/08 HTML / CSS
电子商务专业个人的自我评价
2013/12/19 职场文书
青年志愿者事迹材料
2014/02/07 职场文书
学校社会实践活动总结
2014/07/03 职场文书
大学生党性分析材料
2014/12/19 职场文书
付款承诺函范文
2015/01/21 职场文书
2015年会计个人工作总结
2015/04/02 职场文书
Django实现drf搜索过滤和排序过滤
2021/06/21 Python
【海涛dota解说】海涛小满开黑4v5被破两路翻盘潮汐第一视角解说
2022/04/01 DOTA