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互斥锁、加锁、同步机制、异步通信知识总结
Feb 11 Python
神经网络(BP)算法Python实现及应用
Apr 16 Python
pytorch 把MNIST数据集转换成图片和txt的方法
May 20 Python
Python简单爬虫导出CSV文件的实例讲解
Jul 06 Python
python-tkinter之按钮的使用,开关方法
Jun 11 Python
pyqt弹出新对话框,以及关闭对话框获取数据的实例
Jun 18 Python
python实现遍历文件夹图片并重命名
Mar 23 Python
Pyspark获取并处理RDD数据代码实例
Mar 27 Python
python numpy库np.percentile用法说明
Jun 08 Python
python开发前景如何
Jun 11 Python
详解numpy.ndarray.reshape()函数的参数问题
Oct 13 Python
Python面向对象之内置函数相关知识总结
Jun 24 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
在Windows系统上安装PHP运行环境文字教程
2010/07/19 PHP
主流PHP框架的优缺点对比分析
2014/12/25 PHP
php上传图片类及用法示例
2016/05/11 PHP
利用php的ob缓存机制实现页面静态化方法
2017/07/09 PHP
Laravel如何实现自动加载类
2019/10/14 PHP
php 使用ActiveMQ发送消息,与处理消息操作示例
2020/02/23 PHP
jQuery选择器源码解读(八):addCombinator函数
2015/03/31 Javascript
JavaScript基础教程——入门必看篇
2016/05/20 Javascript
AngularJS基础 ng-mousemove 指令简单示例
2016/08/02 Javascript
浅析上传头像示例及其注意事项
2016/12/14 Javascript
解析Vue2.0双向绑定实现原理
2017/02/23 Javascript
javascript回调函数的概念理解与用法分析
2017/05/27 Javascript
JavaScript实现带有子菜单和控件的slider轮播图效果
2017/11/01 Javascript
setTimeout时间设置为0详细解析
2018/03/13 Javascript
jQuery实现为动态添加的元素绑定事件实例分析
2018/09/07 jQuery
js代码规范之Eslint安装与配置详解
2018/09/08 Javascript
vue组件数据传递、父子组件数据获取,slot,router路由功能示例
2019/03/19 Javascript
Javascript读取上传文件内容/类型/字节数
2019/04/30 Javascript
JavaScript中callee和caller的区别与用法实例分析
2019/06/28 Javascript
node 标准输入流和输出流代码实例
2019/09/19 Javascript
vue 自定义右键样式的实例代码
2019/11/06 Javascript
python字符串的常用操作方法小结
2016/05/21 Python
python的中异常处理机制
2018/08/30 Python
python字典的遍历3种方法详解
2019/08/10 Python
CSS3模拟动画下拉菜单效果
2017/04/12 HTML / CSS
英国领先的运动物理治疗供应公司:Vivomed
2018/07/14 全球购物
焊接专业毕业生求职信
2013/10/01 职场文书
学生就业推荐信
2013/11/13 职场文书
房地产出纳岗位职责
2013/12/01 职场文书
四年的大学生生活自我评价
2013/12/09 职场文书
初二物理教学反思
2014/01/29 职场文书
食品业务员岗位职责
2014/03/18 职场文书
农村党支部书记四风问题个人对照检查材料
2014/09/21 职场文书
2014年会计个人工作总结
2014/11/24 职场文书
医德医风学习心得体会
2016/01/25 职场文书
JavaScript中MutationObServer监听DOM元素详情
2021/11/27 Javascript