什么是粘包问题

  tcp是流体协议. 其nagle算法会将数据量较小. 并且发送间隔时间较短的多个数据包合并为一个发送. 网络传输的时候是一段一段字节流的发送. 在接收方看来根本不知道字节流从何开始. 在哪里结束. 所以粘包问题就是接收方不知道消息之间的界限. 不止到一次性提取多少数据导致的

  而udp协议的是面向消息的协议. 每一段的udp都是一段消息. 应用程序必须以消息作为单位提取. 不能提取任意自己的数据. 所以不存在粘包问题

怎么解决粘包问题

​ 设置一个固定的报头. 报头中含有真实数据的长度信息. 然后客户端就可以根据报头的数据去接收相应字节. 从而避免粘包现象. 总结起来就是一开始将真实数据长度通过报头传递给客户端. 后面都是环环相扣

具体代码

​ 前面都是理论部分. 后面咱们来看看怎么进行实操解决粘包问题. 解决粘包问题的关键就是让客户端知道数据之间的界限在哪.

# 服务端.py

# -*- encoding:utf-8 -*-
# @time: 2022/7/30 13:07
# @author: Maxs_hu
"""
以前有种比较low的方式(alex)是使用time.sleep将数据流之间断开. 当然这种自己设置网络延迟的方式当然是不可取的
""" from socket import *
import subprocess
import json
import struct socket = socket(AF_INET, SOCK_STREAM)
socket.bind(('127.0.0.1', 8000))
socket.listen(5) while True: # 链接循环
print('---服务器开始运行---')
conn, client_addr = socket.accept()
print(client_addr) while True:
try:
cmd = conn.recv(1024)
if len(cmd) == 0:
break
obj = subprocess.run(cmd.decode('utf8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
encoding='gbk'
)
stdout = obj.stdout.encode('utf8')
stderr = obj.stderr.encode('utf8')
data_size = len(stderr+stdout)
# 1. 制作合理的表头数据
header_dic = {
'filename': 'a.txt',
'total_size': data_size,
'hashlib': 'fdfadfadf343jkafjdxkfjc'
}
# 将字典转化成可以传输的格式. 并计算出len
header_json = json.dumps(header_dic)
header_byte = header_json.encode('utf8')
header_len = struct.pack('i', len(header_byte)) # 1. 先将表头长度进行传递
conn.send(header_len) # 2. 再将表头数据进行传输
conn.send(header_byte) # 3. 在传输真实的数据
conn.send(stderr+stdout)
except ConnectionResetError:
break conn.close()
# 客户端.py

# -*- encoding:utf-8 -*-
# @time: 2022/7/30 13:07
# @author: Maxs_hu
from socket import *
import struct
import json client = socket(AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1', 8000)) while True:
cmd = input('请输入命令>>>').strip()
if len(cmd) == 0:
break
client.send(cmd.encode("utf8"))
# 1. 先接收表头长度
header_len = client.recv(4)
header_size = struct.unpack('i', header_len)[0] # 2. 根据表头的长度去接收表头
header = client.recv(header_size) # 解析表头数据
header_dic = json.loads(header.decode('utf8'))
print(header_dic)
total_size = header_dic['total_size'] recv_size = 0
data = b''
while recv_size < total_size:
data += client.recv(1024)
recv_size = len(data)
print(data.decode('utf8'))
client.close()

最新文章

  1. Git: untrack a file in local repo only and keep it in the remote repo
  2. html5 canvas围绕中心点旋转
  3. 洛谷P1738 洛谷的文件夹
  4. js get 传参 汉字 乱码问题
  5. Tomcat找不到service.bat文件
  6. Unix/Linux环境C编程新手教程(12) openSUSECCPP以及Linux内核驱动开发环境搭建
  7. 原创:C sharp 中 Enum的几点小 Tips
  8. android Mvp简单实用
  9. 利用HttpOnly来防御xss攻击
  10. Treap初步
  11. idea 安装热部署插件
  12. scalajs_初体验
  13. 使用mybatis插入自增主键ID的数据后返回自增的ID
  14. 全球性WannaCry蠕虫勒索病毒感染前后应对措施
  15. 简单介绍python的双向队列
  16. 基于微服务的DevOps落地指南 交付效率提升40%
  17. python httpserver
  18. Tensorflow生成唐诗和歌词(上)
  19. 7th,Python基础4——迭代器、生成器、装饰器、Json&amp;pickle数据序列化、软件目录结构规范
  20. Codeforces 1053 C - Putting Boxes Together

热门文章

  1. 思索 p5.js 的最佳实践
  2. CAD图与互联网地图网页端相互叠加显示技术分析和实现
  3. cpulimit-限制CPU速率
  4. 第31章 Spring bean 作用域
  5. 使用 Vite 插件开发构建 Tampermonkey 用户脚本
  6. 聊聊OOP中的设计原则以及访问者模式
  7. 我的第一篇随笔-Test
  8. 2021.05.05【NOIP提高B组】模拟 总结
  9. c++ 线段树
  10. 百度地图API 地图圈区域并计算坐标点是否在区域内