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测试驱动开发实例
Oct 08 Python
python判断windows系统是32位还是64位的方法
May 11 Python
Python爬虫辅助利器PyQuery模块的安装使用攻略
Apr 24 Python
Python+OpenCV图片局部区域像素值处理详解
Jan 23 Python
Django框架设置cookies与获取cookies操作详解
May 27 Python
python读写csv文件实例代码
Jul 05 Python
在pytorch中查看可训练参数的例子
Aug 18 Python
python 读取数据库并绘图的实例
Dec 03 Python
基于Python脚本实现邮件报警功能
May 20 Python
浅析Python 抽象工厂模式的优缺点
Jul 13 Python
python连接mysql数据库并读取数据的实现
Sep 25 Python
pytorch 如何使用amp进行混合精度训练
May 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
刚才在简化php的库,结果发现很多东西
2006/12/31 PHP
php一些公用函数的集合
2008/03/27 PHP
php中sprintf与printf函数用法区别解析
2014/02/17 PHP
phpmyadmin下载、安装、配置教程
2017/05/16 PHP
Javascript 判断是否存在函数的方法
2013/01/03 Javascript
javascript中日期转换成时间戳的小例子
2013/03/21 Javascript
js实现根据身份证号自动生成出生日期
2015/12/15 Javascript
BootStrap入门教程(二)之固定的内置样式
2016/09/19 Javascript
jquery实现刷新随机变化样式特效(tag标签样式)
2017/02/03 Javascript
JS实现线性表的链式表示方法示例【经典数据结构】
2017/04/11 Javascript
浅谈Vue数据绑定的原理
2018/01/08 Javascript
浅谈Webpack 是如何加载模块的
2018/05/24 Javascript
详解基于vue-cli3.0如何构建功能完善的前端架子
2018/10/09 Javascript
javascript实现滚动条效果
2020/03/24 Javascript
Postman如何实现参数化执行及断言处理
2020/07/28 Javascript
JS实现京东商品分类侧边栏
2020/12/11 Javascript
Python读取Excel表格,并同时画折线图和柱状图的方法
2018/10/14 Python
Gauss-Seidel迭代算法的Python实现详解
2019/06/29 Python
python基于socket实现的UDP及TCP通讯功能示例
2019/11/01 Python
python3 常见解密加密算法实例分析【base64、MD5等】
2019/12/19 Python
python不相等的两个字符串的 if 条件判断为True详解
2020/03/12 Python
python对一个数向上取整的实例方法
2020/06/18 Python
Python根据字典的值查询出对应的键的方法
2020/09/30 Python
pymongo insert_many 批量插入的实例
2020/12/05 Python
如何用Java实现列出某个目录下的所有子目录
2015/07/20 面试题
给老婆大人的检讨书
2014/02/24 职场文书
2014年关于两会精神的心得体会
2014/03/17 职场文书
教师对学生的评语
2014/04/28 职场文书
社区志愿者活动总结
2014/06/26 职场文书
爱祖国爱家乡演讲稿
2014/09/02 职场文书
群众路线剖析材料
2014/09/30 职场文书
离退休人员聘用协议书
2014/11/24 职场文书
社区端午节活动总结
2015/02/11 职场文书
使用golang编写一个并发工作队列
2021/05/08 Golang
教你利用Nginx 服务搭建子域环境提升二维地图加载性能的步骤
2021/09/25 Servers
idea下配置tomcat避坑详解
2022/04/12 Servers