Python socket连接中的粘包、精确传输问题实例分析


Posted in Python onMarch 24, 2020

本文实例讲述了Python socket连接中的粘包、精确传输问题。分享给大家供大家参考,具体如下:

粘包:

  • 发生原因:

当调用send的时候,数据并不是即时发给客户端的。而是放到了系统的socket发送缓冲区里,等缓冲区满了、或者数据等待超时了,数据才会发送,所以有时候发送太快的话,前一份数据还没有传给客户端,那么这份数据和上一份数据一起发给客户端的时候就会造成“粘包” 。

  • 解决方案:

解决根源的思想是避免不同段的数据一起发送。

    1. 方案1:前一段数据send完后,等待一段时间再send第二段数据。缺点:时间效率低,而且也无法完全避免问题【因为不清楚该设置多少时间才能保证前一份数据已经发送】
    2. 方案2:握手机制:前一段数据send完后,尝试recv,等待客户端回应,确认第一段数据发送完后,再send第二段数据。完美方案?

方案二的演示:

服务端【发送方】代码:

import socket

server=socket.socket()
server.bind(("localhost",1234))
server.listen()

while True:
  print("正在等待。。。")
  conn,addr=server.accept()
  while True:
    try:
      conn.send(b"first info")
      ack=conn.recv(1024) #接收客户端确认
      print(ack)
      conn.send(b"second info")
    except ConnectionResetError as e:
      print(e)
      break

server.close()

客户端【接收方】代码:

import socket

client=socket.socket()

client.connect(("localhost",1234))

data=client.recv(1024)
print(data.decode())
client.send(b"ack")#发送确认
data=client.recv(1024)
print(data.decode())
client.close()

不精确传输问题:

发生原因:

由于数据太大,发送方一次send不完,而接收方只recv一次,使得影响了后面数据的传输

解决方案:

解决根源的思想是改变recv的次数。

  • 方案:将数据的大小发给接收方,让接收方来决定recv的次数

方案实现代码【以解决长数据shell命令传输为例】:

服务端【发送方】:

import socket,os

server=socket.socket()
server.bind(("localhost",1234))
server.listen()
while True:
  print("正在等待...")
  conn,addr=server.accept()
  print("连接成功!")
  while True:
    try:
      cmd=conn.recv(1024)
      data=os.popen(cmd.decode()).read()
      # print(data)
      cmd_len=len(data.encode())
      print(cmd_len)
      #发现这里如果cmd_len为0会导致异常,有些是没有返回值的command
      if cmd_len==0:
        data="command has nothing return"
        cmd_len=len(data.encode())
      ##因为这里前面没有发送操作,所以不用担心粘包,如果有则要考虑处理
      conn.send(str(cmd_len).encode())#因为len结果是int,所以还要转换
      #这里要处理粘包
      ack=conn.recv(1024)
      conn.send(data.encode())
    except ConnectionResetError as e:
      print(e)
      break

server.close()

客户端【接收方】:

import socket

client=socket.socket()
client.connect(("localhost",1234))
while True:

  cmd = input(">>:")
  client.send(cmd.encode())
  data_len=client.recv(1024)
  data_len=int(data_len.decode())
  print(data_len)
  recv_len=0
  client.send(b'ack')
  total_data=b''
  while recv_len<data_len:
    data=client.recv(1024)
    recv_len+=len(data)
    total_data+=data
  print(total_data.decode())
client.close()
  • 利用这个原理可以实现文件传输,只要能确定接受次数,就能保证文件传输的大小正确。

更多关于Python相关内容可查看本站专题:《Python Socket编程技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
详解Python程序与服务器连接的WSGI接口
Apr 29 Python
matplotlib 纵坐标轴显示数据值的实例
May 25 Python
mac下给python3安装requests库和scrapy库的实例
Jun 13 Python
python实现名片管理系统
Nov 29 Python
Python3.4学习笔记之列表、数组操作示例
Mar 01 Python
pandas实现to_sql将DataFrame保存到数据库中
Jul 03 Python
django 基于中间件实现限制ip频繁访问过程详解
Jul 30 Python
python 三元运算符使用解析
Sep 16 Python
Python环境下安装PyGame和PyOpenGL的方法
Mar 25 Python
python如何随机生成高强度密码
Aug 19 Python
Python批量修改xml的坐标值全部转为整数的实例代码
Nov 26 Python
python数据分析之用sklearn预测糖尿病
Apr 22 Python
Pyqt5 关于流式布局和滚动条的综合使用示例代码
Mar 24 #Python
Python+Appium实现自动化测试的使用步骤
Mar 24 #Python
Python3标准库之dbm UNIX键-值数据库问题
Mar 24 #Python
python网络编程socket实现服务端、客户端操作详解
Mar 24 #Python
python实现批量修改文件名
Mar 23 #Python
Python3 filecmp模块测试比较文件原理解析
Mar 23 #Python
python实现遍历文件夹图片并重命名
Mar 23 #Python
You might like
php编写的抽奖程序中奖概率算法
2015/05/14 PHP
yii2 开发api接口时优雅的处理全局异常的方法
2019/05/14 PHP
jquery $.each()使用探讨
2013/09/23 Javascript
jquery跟js初始化加载的多种方法及区别介绍
2014/04/02 Javascript
在JavaScript中处理时间之setMinutes()方法的使用
2015/06/11 Javascript
如何解决easyui自定义标签 datagrid edit combobox 手动输入保存不上
2015/12/26 Javascript
jquery拖动层效果插件用法实例分析(附demo源码)
2016/04/28 Javascript
JavaScript数组去重由慢到快由繁到简(优化篇)
2016/08/26 Javascript
JS正则表达式修饰符中multiline(/m)用法分析
2016/12/27 Javascript
学习使用jQuery表单验证插件和日历插件
2017/02/13 Javascript
Js中async/await的执行顺序详解
2017/09/22 Javascript
vue.js给动态绑定的radio列表做批量编辑的方法
2018/02/28 Javascript
使用Vue构建可重用的分页组件
2018/03/26 Javascript
vue awesome swiper异步加载数据出现的bug问题
2018/07/03 Javascript
JavaScript实用代码小技巧
2018/08/23 Javascript
angularjs1.5 组件内用函数向外传值的实例
2018/09/30 Javascript
python线程锁(thread)学习示例
2013/12/04 Python
Python中集合类型(set)学习小结
2015/01/28 Python
浅谈python正则的常用方法 覆盖范围70%以上
2018/03/14 Python
python pandas消除空值和空格以及 Nan数据替换方法
2018/10/30 Python
selenium+python自动化测试环境搭建步骤
2019/06/03 Python
用Python实现将一张图片分成9宫格的示例
2019/07/05 Python
欧洲第一中国智能手机和平板电脑网上商店:CECT-SHOP
2018/01/08 全球购物
澳大利亚珠宝商:Shiels
2019/10/06 全球购物
应届护士求职信范文
2014/01/26 职场文书
大学生个人自荐信样本
2014/03/02 职场文书
会计岗位职责模板
2014/03/12 职场文书
工业自动化专业自荐信范文
2014/04/10 职场文书
空气的环保标语
2014/06/12 职场文书
行政文员实习自我鉴定范文
2014/09/14 职场文书
商品陈列协议书
2014/09/29 职场文书
2014年教师思想工作总结
2014/12/03 职场文书
安全员岗位职责范本
2015/04/11 职场文书
MySQL实例精讲单行函数以及字符数学日期流程控制
2021/10/15 MySQL
Android Studio实现简易进制转换计算器
2022/05/20 Java/Android
使用 DataAnt 监控 Apache APISIX的原理解析
2022/07/07 Servers