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基础教程之Hello World!
Aug 29 Python
Python记录详细调用堆栈日志的方法
May 05 Python
在Django的URLconf中进行函数导入的方法
Jul 18 Python
Python使用Beautiful Soup包编写爬虫时的一些关键点
Jan 20 Python
Python二叉树的遍历操作示例【前序遍历,中序遍历,后序遍历,层序遍历】
Dec 24 Python
浅谈Python编程中3个常用的数据结构和算法
Apr 30 Python
使用Django搭建web服务器的例子(最最正确的方式)
Aug 29 Python
python文件读写代码实例
Oct 21 Python
详解Django admin高级用法
Nov 06 Python
Python with标签使用方法解析
Jan 17 Python
python3 自动打印出最新版本执行的mysql2redis实例
Apr 09 Python
python装饰器代码深入讲解
Mar 01 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桌面中心(一) 创建数据库
2007/03/11 PHP
php 接口类与抽象类的实际作用
2009/11/26 PHP
PHP统计当前在线用户数实例讲解
2015/10/21 PHP
ThinkPHP框架下微信支付功能总结踩坑笔记
2019/04/10 PHP
js 强制弹出窗口代码研究-又一款代码
2010/03/20 Javascript
最短的javascript:地址栏载入脚本代码
2011/10/13 Javascript
引用 js在IE与FF之间的区别详细解析
2013/11/20 Javascript
原生JavaScript实现瀑布流布局
2020/06/28 Javascript
javascript拖拽应用实例(二)
2016/03/25 Javascript
JavaScript中自带的 reduce()方法使用示例详解
2016/08/10 Javascript
JS+CSS3模拟溢出滚动效果
2016/08/12 Javascript
ES6学习教程之Map的常用方法总结
2017/08/03 Javascript
详解从Vue-router到html5的pushState
2018/07/21 Javascript
利用Vconsole和Fillder进行移动端抓包调试方法
2019/03/05 Javascript
[03:15]2014DOTA2国际邀请赛 专访国士无双信心满满
2014/07/12 DOTA
[01:26]DOTA2荣耀之路2:iG,China
2018/05/24 DOTA
python使用urllib模块开发的多线程豆瓣小站mp3下载器
2014/01/16 Python
用Python编写一个简单的Lisp解释器的教程
2015/04/03 Python
python使用wxPython打开并播放wav文件的方法
2015/04/24 Python
Python探索之创建二叉树
2017/10/25 Python
利用Python如何生成便签图片详解
2018/07/09 Python
解决tensorflow测试模型时NotFoundError错误的问题
2018/07/26 Python
python opencv将图片转为灰度图的方法示例
2019/07/31 Python
python处理excel绘制雷达图
2019/10/18 Python
Python Tkinter模块 GUI 可视化实例
2019/11/20 Python
django 模型字段设置默认值代码
2020/07/15 Python
python中实现栈的三种方法
2020/12/19 Python
你应该知道的30个css选择器
2014/03/19 HTML / CSS
护士岗位职责
2014/02/16 职场文书
医学生求职自荐书
2014/06/12 职场文书
企业授权委托书范本
2014/09/22 职场文书
预备党员介绍人意见
2015/06/01 职场文书
婚宴致辞
2015/07/28 职场文书
2016中考冲刺决心书
2015/09/22 职场文书
毕业生求职自荐信(2016最新版)
2016/01/28 职场文书
MySQL GTID复制的具体使用
2022/05/20 MySQL