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获取远程文件大小的函数代码分享
May 13 Python
Python中的Classes和Metaclasses详解
Apr 02 Python
Python使用multiprocessing创建进程的方法
Jun 04 Python
python根据日期返回星期几的方法
Jul 06 Python
两个使用Python脚本操作文件的小示例分享
Aug 27 Python
Python使用urllib2模块抓取HTML页面资源的实例分享
May 03 Python
Python基础学习之类与实例基本用法与注意事项详解
Jun 17 Python
python多线程共享变量的使用和效率方法
Jul 16 Python
python框架django项目部署相关知识详解
Nov 04 Python
解决pycharm debug时界面下方不出现step等按钮及变量值的问题
Jun 09 Python
Python数据库封装实现代码示例解析
Sep 05 Python
python 基于opencv操作摄像头
Dec 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
肝肠寸断了解下!盘点史上最伤心的十大动漫
2020/03/04 日漫
PHP7生产环境队列Beanstalkd用法详解
2020/05/19 PHP
Javascript 错误处理的几种方法
2009/06/13 Javascript
IE和Firefox下event事件杂谈
2009/12/18 Javascript
用jquery实现学校的校历(asp.net+jquery ui 1.72)
2010/01/01 Javascript
js 数组克隆方法 小结
2010/03/20 Javascript
js 替换功能函数,用正则表达式解决,js的全部替换
2010/12/08 Javascript
用js小类库获取浏览器的高度和宽度信息
2012/01/15 Javascript
JavaScript实现QueryString获取GET参数的方法
2013/07/02 Javascript
往光标所在位置插入值的js代码
2013/09/22 Javascript
jQuery中delegate和on的用法与区别详细解析
2014/01/26 Javascript
jquery制作弹窗提示窗口代码分享
2014/03/02 Javascript
javascript生成随机颜色示例代码
2014/05/05 Javascript
TypeScript具有的几个不同特质
2015/04/07 Javascript
在Ubuntu系统上安装Node.JS的教程
2015/10/15 Javascript
javascript实现简单的全选和反选功能
2016/01/05 Javascript
快速掌握Node.js模块封装及使用
2016/03/21 Javascript
jQuery soColorPacker 网页拾色器
2016/06/22 Javascript
JavaScript实现向select下拉框中添加和删除元素的方法
2017/03/07 Javascript
js清除浏览器缓存的几种方法
2017/03/15 Javascript
JS排序算法之冒泡排序,选择排序与插入排序实例分析
2017/12/13 Javascript
JavaScript设计模式之职责链模式应用示例
2018/08/07 Javascript
在Python中使用异步Socket编程性能测试
2014/06/25 Python
python中二维阵列的变换实例
2014/10/09 Python
Python中使用urllib2模块编写爬虫的简单上手示例
2016/01/20 Python
python将ansible配置转为json格式实例代码
2017/05/15 Python
python dict乱码如何解决
2020/06/07 Python
Python3基于plotly模块保存图片表格
2020/08/03 Python
世界最大的私人旅行指南出版商:孤独星球
2016/08/23 全球购物
香港个人化生活购物网站:Ballyhoo Limited
2016/09/10 全球购物
美国廉价机票预订网站:Cheapfaremart
2018/04/28 全球购物
工作态度检讨书
2014/02/11 职场文书
《去年的树》教学反思
2014/04/11 职场文书
办公室文员岗位职责范本
2014/06/12 职场文书
民主生活会对照检查材料
2014/09/22 职场文书
2014年终工作总结范本
2014/12/15 职场文书