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通过pil模块获得图片exif信息的方法
Mar 16 Python
python批量赋值操作实例
Oct 22 Python
Windows系统Python直接调用C++ DLL的方法
Aug 01 Python
django框架创建应用操作示例
Sep 26 Python
python使用opencv在Windows下调用摄像头实现解析
Nov 26 Python
在Pytorch中计算自己模型的FLOPs方式
Dec 30 Python
pytorch中使用cuda扩展的实现示例
Feb 12 Python
python3 简单实现组合设计模式
Jul 02 Python
Selenium webdriver添加cookie实现过程详解
Aug 12 Python
python wsgiref源码解析
Feb 06 Python
No module named ‘win32gui‘ 的解决方法(踩坑之旅)
Feb 18 Python
Python用tkinter实现自定义记事本的方法详解
Mar 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
php分页思路以及在ZF中的使用
2012/05/30 PHP
php中的Base62类(适用于数值转字符串)
2013/08/12 PHP
PHP依赖倒置(Dependency Injection)代码实例
2014/10/11 PHP
PHP sleep()函数, usleep()函数
2016/08/25 PHP
php 防止表单重复提交两种实现方法
2016/11/03 PHP
thinkPHP多语言切换设置方法详解
2016/11/11 PHP
document.onreadystatechange事件的用法分析
2009/10/17 Javascript
分享10篇优秀的jQuery幻灯片制作教程及应用案例
2011/04/16 Javascript
单击浏览器右上角的X关闭窗口弹出提示的小例子
2013/06/12 Javascript
Jquery 获取对象的几种方式介绍
2014/01/17 Javascript
jquery选择器原理介绍($()使用方法)
2014/03/25 Javascript
jQuery.extend 函数及用法详细
2015/09/06 Javascript
Javascript在IE和Firefox浏览器常见兼容性问题总结
2016/08/03 Javascript
原生js实现打字动画游戏
2017/02/04 Javascript
JS实现页面打印功能
2017/03/16 Javascript
基于IView中on-change属性的使用详解
2018/03/15 Javascript
elementUI select组件使用及注意事项详解
2019/05/29 Javascript
[02:32]DOTA2完美大师赛场馆静安体育中心观赛全攻略
2017/11/08 DOTA
[49:29]LGD vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
在Python中处理字符串之ljust()方法的使用简介
2015/05/19 Python
Python3多线程操作简单示例
2018/05/22 Python
django 实现编写控制登录和访问权限控制的中间件方法
2019/01/15 Python
如何在Django中添加没有微秒的 DateTimeField 属性详解
2019/01/30 Python
Python第三方库face_recognition在windows上的安装过程
2019/05/03 Python
python实现最大优先队列
2019/08/29 Python
python写一个随机点名软件的实例
2019/11/28 Python
Python lxml模块的基本使用方法分析
2019/12/21 Python
如何使用pandas读取txt文件中指定的列(有无标题)
2020/03/05 Python
使用python实现飞机大战游戏
2020/03/23 Python
想学画画?python满足你!
2020/12/24 Python
内衣营销方案
2014/03/15 职场文书
气象学专业个人求职信
2014/03/15 职场文书
社区健康教育实施方案
2014/03/18 职场文书
python执行js代码的方法
2021/05/13 Python
js中Map和Set的用法及区别实例详解
2022/02/15 Javascript
git中cherry-pick命令的使用教程
2022/06/25 Servers