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 相关文章推荐
tensorflow输出权重值和偏差的方法
Feb 10 Python
python读取视频流提取视频帧的两种方法
Oct 22 Python
Django进阶之CSRF的解决
Aug 01 Python
Python3实现腾讯云OCR识别
Nov 27 Python
python使用selenium实现批量文件下载
Mar 11 Python
Python3 无重复字符的最长子串的实现
Oct 08 Python
pycharm运行程序时看不到任何结果显示的解决
Feb 21 Python
使用python客户端访问impala的操作方式
Mar 28 Python
Python小白垃圾回收机制入门
Jun 09 Python
Python变量格式化输出实现原理解析
Aug 06 Python
超级实用的8个Python列表技巧
Aug 24 Python
python 下载文件的几种方式分享
Apr 07 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
PHP3 safe_mode 失效漏洞
2006/10/09 PHP
PHP编程过程中需要了解的this,self,parent的区别
2009/12/30 PHP
php操作excel文件 基于phpexcel
2010/07/02 PHP
php_imagick实现图片剪切、旋转、锐化、减色或增加特效的方法
2014/12/15 PHP
PHP+MySQL插入操作实例
2015/01/21 PHP
php简单获取目录列表的方法
2015/03/24 PHP
jquery 图片预加载 自动等比例缩放插件
2008/12/25 Javascript
JavaScript 工具库 Cloudgamer JavaScript Library v0.1 发布
2009/10/29 Javascript
JSON+JavaScript处理JSON的简单例子
2013/03/20 Javascript
了解了这些才能开始发挥jQuery的威力
2013/10/10 Javascript
JS实现弹性漂浮效果的广告代码
2015/09/02 Javascript
详解JavaScript数组的操作大全
2015/10/19 Javascript
基于jQuery实现仿QQ空间送礼物功能代码
2016/05/24 Javascript
浅谈vue中慎用style的scoped属性
2017/11/28 Javascript
使用axios发送post请求,将JSON数据改为form类型的示例
2019/10/31 Javascript
[01:20]2018DOTA2亚洲邀请赛总决赛战队Mineski晋级之路
2018/04/07 DOTA
Python实现多行注释的另类方法
2014/08/22 Python
Python生成随机密码
2015/03/10 Python
Python中的字典与成员运算符初步探究
2015/10/13 Python
python文件操作之批量修改文件后缀名的方法
2018/08/10 Python
详解用python写一个抽奖程序
2019/05/10 Python
Django模板Templates使用方法详解
2019/07/19 Python
10个Python面试常问的问题(小结)
2019/11/20 Python
Python 如何调试程序崩溃错误
2020/08/03 Python
python爬虫用scrapy获取影片的实例分析
2020/11/23 Python
H5混合开发app如何升级的方法
2018/01/10 HTML / CSS
软件缺陷的分类都有哪些
2014/08/22 面试题
旅游管理专业生自荐信范文
2014/01/02 职场文书
高一地理教学反思
2014/01/18 职场文书
市级文明单位申报材料
2014/05/07 职场文书
2014年幼师工作总结
2014/11/22 职场文书
2016自主招生教师推荐信范文
2015/03/23 职场文书
公司承诺书格式范文
2015/04/28 职场文书
JavaScript实现队列结构过程
2021/12/06 Javascript
Django框架中表单的用法
2022/06/10 Python
Go结合Gin导出Mysql数据到Excel表格
2022/08/05 Golang