TCP粘包问题
一、粘包问题
1、粘包问题
接收方:我不知道我要接收的数据的总长度
发送方:由于tcp协议的内部优化算法:会将数据量比较小的并且时间间隔比较短的数据一次性打包发送
2、如何解决
第一步:发送数据直接先告诉对方数据量的大小,让对方知道怎么接收你的数据。
第二步:利用struct模块定制我们自己的消息传输协议:制作字典报头
3、最终版本解决粘包问题
客户端:
①制作字典报头
②发送报头
③再发送字典
④再发你的真实数据
服务端:
①先收4个长度的报头
②解析报头,获取字典长度
③接收字典(反序列化) ——>> 获取字典里面所有信息
④接收真实数据
4、代码(简单版)
服务端:
客户端:
5、代码(终极版)
服务端:
客户端:
六、struct模块使用
import struct data = 'dfsafsagdsfgfafsdafsdafafryuio' # 服务端 res = struct.pack('i', len(data)) # 打包:把一个数据打包为长度固定为4 print(len(res)) # 4 print(res) # b'\x1e\x00\x00\x00' # 客户端 ret = struct.unpack('i', res)[0] # 解包:数据真实长度 print(ret) # 30
二、大文件上传(解决粘包问题代码)
①客户端
import socket, os, json, struct client = socket.socket() client.connect(('127.0.0.1', 8080)) # 文件大小 file_size = os.path.getsize(r'D:\Desktop\wendang.txt') # 文件名 file_name = '计算机五大.txt' # 然后定义一个字典 d = { 'file_name': file_name, 'file_size': file_size, 'msg': '成功上传' } # 定义好字典后,先去转一下json,然后encode data_bytes = json.dumps(d).encode('utf-8') # 制作字典的报头 header = struct.pack('i', len(data_bytes)) # 发送报头 client.send(header) # 发送字典 client.send(data_bytes) # 然后发送真实数据:打开文件,一行一行读取出来,一行一行的发送 with open(r'D:\Desktop\wendang.txt', 'rb') as f: for line in f: client.send(line)
②服务端
import socket, json, struct server = socket.socket() server.bind(('127.0.0.1', 8080)) server.listen(5) while True: conn, addr = server.accept() while True: try: # 先接收报头 header = conn.recv(4) # 解析报头,获取字典长度 header_len = struct.unpack('i', header)[0] # 接收字典 header_bytes = conn.recv(header_len) header_dic = json.loads(header_bytes.decode('utf_8')) print(header_dic) # 打印字典 # 循环接收文件,存储到本地 file_size = header_dic.get('file_size') file_name = header_dic.get('file_name') recv_size = 0 # 文件操作 with open(file_name, 'wb') as f: while recv_size < file_size: # 循环接收 data = conn.recv(1024) f.write(data) recv_size += len(data) print(header_dic.get('msg')) # 文件上传成功后的提示信息 except ConnectionResetError: break conn.close()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现