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 相关文章推荐
Python2.x中文乱码问题解决方法
Jun 02 Python
Python实现优先级队列结构的方法详解
Jun 02 Python
python实现微信远程控制电脑
Feb 22 Python
python实现12306抢票及自动邮件发送提醒付款功能
Mar 08 Python
详解python3中tkinter知识点
Jun 21 Python
用于业余项目的8个优秀Python库
Sep 21 Python
Python字典fromkeys()方法使用代码实例
Jul 20 Python
Python 实现图片转字符画的示例(静态图片,gif皆可)
Nov 05 Python
python 对象真假值的实例(哪些视为False)
Dec 11 Python
详解python 条件语句和while循环的实例代码
Dec 28 Python
Python insert() / append() 用法 Leetcode实战演示
Mar 31 Python
Python实战之大鱼吃小鱼游戏的实现
Apr 01 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
Terran历史背景
2020/03/14 星际争霸
解析linux下安装memcacheq(mcq)全过程笔记
2013/06/27 PHP
PHP JSON格式的中文显示问题解决方法
2015/04/09 PHP
如何使用Gitblog和Markdown建自己的博客
2015/07/31 PHP
基于php判断客户端类型
2016/10/14 PHP
php array_pop 删除数组最后一个元素实例
2016/11/02 PHP
PHP编程中的Session阻塞问题与解决方法分析
2017/08/07 PHP
php 字符串中是否包含指定字符串的多种方法
2018/04/12 PHP
extJs 文本框后面加上说明文字+下拉列表选中值后触发事件
2009/11/27 Javascript
javascript中数组array及string的方法总结
2014/11/28 Javascript
jquery实现图片水平滚动效果代码分享
2015/08/26 Javascript
jquery UI Datepicker时间控件的使用方法(终结版)
2015/11/07 Javascript
js手机号4位显示空格,银行卡每4位显示空格效果
2017/03/23 Javascript
Nuxt.js实现校验访问浏览器类型的中间件
2018/08/24 Javascript
jquery向后台提交数组的代码分析
2020/02/20 jQuery
vue Element左侧无限级菜单实现
2020/06/10 Javascript
[49:05]OG vs Newbee 2019DOTA2国际邀请赛淘汰赛 胜者组 BO3 第二场 8.21.mp4
2020/07/19 DOTA
Python中的字符串查找操作方法总结
2016/06/27 Python
分享几道你可能遇到的python面试题
2017/07/24 Python
Pandas GroupBy对象 索引与迭代方法
2018/11/16 Python
Python OpenCV对本地视频文件进行分帧保存的实例
2019/01/08 Python
Python3内置模块random随机方法小结
2019/07/13 Python
Django中Middleware中的函数详解
2019/07/18 Python
利用Python脚本实现自动刷网课
2020/02/03 Python
利用CSS3的border-radius绘制太极及爱心图案示例
2016/05/17 HTML / CSS
Stefania Mode美国:奢华设计师和时尚服装
2018/01/07 全球购物
美国半成品食材配送服务商:Home Chef
2018/01/25 全球购物
Aosom西班牙:家具在线商店
2020/06/11 全球购物
高级文秘工作总结的自我评价
2013/09/28 职场文书
高中语文教学反思
2014/01/16 职场文书
四年级科学教学反思
2014/02/10 职场文书
一份文言文检讨书
2014/09/13 职场文书
画展观后感
2015/06/17 职场文书
工作简报范文
2015/07/21 职场文书
孙振耀退休感言
2015/08/01 职场文书
公司保密管理制度
2015/08/04 职场文书