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计算最小优先级队列代码分享
Dec 18 Python
python循环监控远程端口的方法
Mar 14 Python
简单介绍Python中的floor()方法
May 15 Python
python 迭代器和iter()函数详解及实例
Mar 21 Python
Python机器学习之决策树算法
Dec 22 Python
OpenCV2.3.1+Python2.7.3+Numpy等的配置解析
Jan 05 Python
python+tkinter编写电脑桌面放大镜程序实例代码
Jan 16 Python
python如何通过twisted实现数据库异步插入
Mar 20 Python
python3库numpy数组属性的查看方法
Apr 17 Python
Python Opencv 通过轨迹(跟踪)栏实现更改整张图像的背景颜色
Mar 09 Python
Python绘图之柱形图绘制详解
Jul 28 Python
pyqt5 textEdit、lineEdit操作的示例代码
Aug 12 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 GD绘制24小时柱状图
2008/06/28 PHP
PHP实现服务器状态监控的方法
2014/12/09 PHP
PHP输出九九乘法表代码实例
2015/03/27 PHP
详解WordPress中过滤链接与过滤SQL语句的方法
2015/12/18 PHP
PHP批量删除jQuery操作
2017/07/23 PHP
JavaScript delete操作符应用实例
2009/01/13 Javascript
Cookie 小记
2010/04/01 Javascript
javascript new fun的执行过程
2010/08/05 Javascript
jquery 删除cookie失效的解决方法
2013/11/12 Javascript
利用javascript数组长度循环数组内所有元素
2013/12/27 Javascript
基于zepto.js实现仿手机QQ空间的大图查看组件ImageView.js详解
2015/03/05 Javascript
jquery实现带缩略图的可定制高度画廊效果(5种)
2015/08/28 Javascript
jquery衣服颜色选取插件效果代码分享
2015/08/28 Javascript
利用jsonp与代理服务器方案解决跨域问题
2017/09/14 Javascript
html中通过JS获取JSON数据并加载的方法
2017/11/30 Javascript
基于node简单实现RSA加解密的方法步骤
2019/03/21 Javascript
JS中FormData类实现文件上传
2020/03/27 Javascript
es6函数之尾调用优化实例分析
2020/04/25 Javascript
Vue路由的模块自动化与统一加载实现
2020/06/05 Javascript
vue axios封装httpjs,接口公用配置拦截操作
2020/08/11 Javascript
python批量导出导入MySQL用户的方法
2013/11/15 Python
2018年Python值得关注的开源库、工具和开发者(总结篇)
2018/01/04 Python
使用Python3+PyQT5+Pyserial 实现简单的串口工具方法
2019/02/13 Python
使用 Supervisor 监控 Python3 进程方式
2019/12/05 Python
Python编译成.so文件进行加密后调用的实现
2019/12/23 Python
Python 实现键盘鼠标按键模拟
2020/11/18 Python
CSS3 重置iphone浏览器按钮input,select等表单元素的默认样式
2014/10/11 HTML / CSS
英国设计师珠宝网站:Joshua James Jewellery
2020/03/01 全球购物
几道Java和数据库的面试题
2013/05/30 面试题
广告传媒专业应届生求职信
2014/03/01 职场文书
公司离职证明范本(5篇)
2014/09/17 职场文书
党员批评与自我批评发言
2014/10/02 职场文书
后进生评语大全
2015/01/04 职场文书
单位接收证明格式
2015/06/18 职场文书
《狼牙山五壮士》教学反思
2016/02/17 职场文书
详解分布式系统中如何用python实现Paxos
2021/05/18 Python