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的ORM框架中的SQLAlchemy库的映射关系
Apr 25 Python
python如何为被装饰的函数保留元数据
Mar 21 Python
Python中存取文件的4种不同操作
Jul 02 Python
Python for循环中的陷阱详解
Jul 13 Python
python使用matplotlib库生成随机漫步图
Aug 27 Python
python 3.6.4 安装配置方法图文教程
Sep 18 Python
使用python快速在局域网内搭建http传输文件服务的方法
Nov 14 Python
Python Scrapy多页数据爬取实现过程解析
Jun 12 Python
python3.4中清屏的处理方法
Jul 06 Python
Python中实现一行拆多行和多行并一行的示例代码
Sep 06 Python
教你怎么用Python操作MySql数据库
May 31 Python
python三子棋游戏
May 04 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学习之数组的定义和填充
2011/04/17 PHP
ThinkPHP自动验证失败的解决方法
2011/06/09 PHP
解析WordPress中的post_class与get_post_class函数
2016/01/04 PHP
jQuery图片预加载 等比缩放实现代码
2011/10/04 Javascript
Extjs优化(一)删除冗余代码提高运行速度
2013/04/15 Javascript
JavaScript中的方法重载实例
2015/03/16 Javascript
javascript截取字符串小结
2015/04/28 Javascript
JS基于面向对象实现的放烟花效果
2015/05/07 Javascript
JavaScript中函数(Function)的apply与call理解
2015/07/08 Javascript
javascript实现确定和取消提示框效果
2015/07/10 Javascript
jquery判断对象是否为空并遍历对象的简单实例
2016/07/26 Javascript
BOM系列第三篇之定时器应用(时钟、倒计时、秒表和闹钟)
2016/08/17 Javascript
浅谈javascript中的事件冒泡和事件捕获
2016/12/28 Javascript
[js高手之路]原型式继承与寄生式继承详解
2017/08/28 Javascript
基于input动态模糊查询的实现方法
2017/12/12 Javascript
原生js添加一个或多个类名的方法分析
2019/07/30 Javascript
vue 自动化路由实现代码
2019/09/03 Javascript
Vue 如何使用props、emit实现自定义双向绑定的实现
2020/06/05 Javascript
[01:07:19]DOTA2-DPC中国联赛 正赛 CDEC vs XG BO3 第一场 1月19日
2021/03/11 DOTA
python生成随机mac地址的方法
2015/03/16 Python
Python生成密码库功能示例
2017/05/23 Python
Python编程对列表中字典元素进行排序的方法详解
2017/05/26 Python
浅谈pandas筛选出表中满足另一个表所有条件的数据方法
2019/02/08 Python
jupyter notebook 多环境conda kernel配置方式
2020/04/10 Python
如何用 Python 制作一个迷宫游戏
2021/02/25 Python
expedia比利时:预订航班+酒店并省钱
2018/07/13 全球购物
西班牙最大的在线滑板和街头服饰商店:Fillow.net
2019/04/15 全球购物
护士专业推荐信
2013/11/02 职场文书
计算机专业毕业生的自我评价
2013/11/18 职场文书
单位成立周年感言
2014/01/26 职场文书
公司财务流程之主管工作流程
2014/03/03 职场文书
主题教育活动总结
2014/05/05 职场文书
2014教师年度思想工作总结
2014/11/10 职场文书
文言文辞职信
2015/02/28 职场文书
党员干部学习十八届五中全会精神心得体会
2016/01/05 职场文书
position:sticky 粘性定位的几种巧妙应用详解
2021/04/24 HTML / CSS