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单链表实现代码实例
Nov 21 Python
Python切片用法实例教程
Sep 08 Python
Python将list中的string批量转化成int/float的方法
Jun 26 Python
浅谈python函数调用返回两个或多个变量的方法
Jan 23 Python
Python删除n行后的其他行方法
Jan 28 Python
Python实战购物车项目的实现参考
Feb 20 Python
python面试题Python2.x和Python3.x的区别
May 28 Python
Flask框架路由和视图用法实例分析
Nov 07 Python
python 读写文件包含多种编码格式的解决方式
Dec 20 Python
利用python在excel中画图的实现方法
Mar 17 Python
Numpy中np.max的用法及np.maximum区别
Nov 27 Python
python中doctest库实例用法
Dec 31 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
jQuery+php实现ajax文件即时上传的详解
2013/06/17 PHP
解析posix与perl标准的正则表达式区别
2013/06/17 PHP
php实现文件下载功能的几个代码分享
2014/05/10 PHP
php上传文件问题汇总
2015/01/30 PHP
Laravel 5 框架入门(二)构建 Pages 的管理功能
2015/04/09 PHP
深入浅出php socket编程
2015/05/13 PHP
YII框架关联查询操作示例
2019/04/29 PHP
Javascript中的数学函数集合
2007/05/08 Javascript
建立良好体验度的Web注册系统ajax
2007/07/09 Javascript
有一段有意思的代码-javascript现实多行信息
2007/08/26 Javascript
解决表单中第一个非隐藏的元素获得焦点的一个方案
2009/10/26 Javascript
javascript处理table表格的代码
2010/12/06 Javascript
JS中 用户登录系统的解决办法
2013/04/15 Javascript
如何使用jQUery获取选中radio对应的值(一句代码)
2013/06/03 Javascript
jquery(hide方法)隐藏指定元素实例
2013/11/11 Javascript
js中iframe调用父页面的方法
2014/10/30 Javascript
JS实现键值对遍历json数组功能示例
2018/05/30 Javascript
layui-laydate时间日历控件使用方法详解
2018/11/15 Javascript
实现vuex与组件data之间的数据同步更新方式
2019/11/12 Javascript
Vue如何获取数据列表展示
2019/12/11 Javascript
python中os操作文件及文件路径实例汇总
2015/01/15 Python
python基于右递归解决八皇后问题的方法
2015/05/25 Python
Python遍历某目录下的所有文件夹与文件路径
2018/03/15 Python
Python3处理HTTP请求的实例
2018/05/10 Python
在NumPy中创建空数组/矩阵的方法
2018/06/15 Python
Python通过TensorFLow进行线性模型训练原理与实现方法详解
2020/01/15 Python
LEGO玩具英国官方商店:LEGO Shop GB
2018/03/27 全球购物
Lulu Guinness露露·吉尼斯官网:红唇包
2019/02/03 全球购物
市场营销专业个人求职信范文
2013/12/14 职场文书
《沉香救母》教学反思
2014/04/19 职场文书
市场营销计划书范文
2015/01/16 职场文书
毕业生党员个人总结
2015/02/14 职场文书
妈妈别哭观后感
2015/06/08 职场文书
爱国主义教育基地观后感
2015/06/18 职场文书
2016校本研修培训心得体会
2016/01/08 职场文书
2019入党申请书范文3篇
2019/08/21 职场文书