宁波小型建网站公司,简单的网站建设公司,网站开发模式名词,seo优化厂家为什么会出现黏包问题#xff1f; 首先只有在TCP协议中才会出现黏包现象 是因为TCP协议是面向流的协议 在发送的数据 传输过程中 有缓存机制 来避免数据丢失 因此 在连续发送小数据的时候 以及接收大小不符的时候都容易出现黏包现象 本质还是因为我们在接受数据的时候不知道发…为什么会出现黏包问题 首先只有在TCP协议中才会出现黏包现象 是因为TCP协议是面向流的协议 在发送的数据 传输过程中 有缓存机制 来避免数据丢失 因此 在连续发送小数据的时候 以及接收大小不符的时候都容易出现黏包现象 本质还是因为我们在接受数据的时候不知道发送的数据的长短 怎么解决黏包问题 在接收端发送要发送的数据的大小 一种是不带struct 一种是带struct 定制协议 黏包 http://www.cnblogs.com/Eva-J/articles/8244551.html#_label5 注意只有TCP有粘包现象UDP永远不会粘包 黏包成因 多个send可能会发生黏包现象 优化算法不优化 发生黏包两种现象 情况一 发送方的缓存机制 发送端需要等缓冲区满才发送出去造成粘包发送数据时间间隔很短数据了很小会合到一起产生粘包 情况二 接收方的缓存机制 接收方不及时接收缓冲区的包造成多个包接收客户端发送了一段数据服务端只收了一小部分服务端下次再收的时候还是从缓冲区拿上次遗留的数据产生粘包 如何解决黏包 存在的问题
多了一次交互。程序的运行速度远快于网络传输速度所以在发送一段字节前先用send去发送该字节流长度这种方式会放大网络延迟带来的性能损耗 struct模块 该模块可以把一个类型如数字转成固定长度的bytes 这个模块可以把要发送的数据长度转换成固定长度的字节。这样客户端每次接收消息之前只要先接受这个固定长度字节的内容看一看接下来要接收的信息大小那么最终接受的数据只要达到这个值就停止就能刚好不多不少的接收完整的数据了。 import structret struct.pack(i, 2049) # pack方法将对象转换成固定字节长度bytes类型num struct.unpack(i, ret) # 解包
print(num) # 元组
print(num[0]) # 数字 连续send 连续receive 我们在网络上传输的所有数据都叫数据包 数据包中的数据都叫报文 报文里不只有你的数据 ip地址 mac地址 端口号 所有的报文都有报头 相当于协议 接收多少字节 什么顺序 等等 报头可以自己定制 根据报头来解包接收的数据 复杂的应用上就会用到定制报头 比如传输文件的时候 文件名、大小、类型、路径 网络传输中处处有有协议协议就是一堆报文和报头 ———字节 协议的解析过程我们不需要关心 我们也可以自定制协议 实现一个大文件的上传或下载 客户端作发送端 import socket
import os
import json
import structsk socket.socket()
sk.connect((127.0.0.1,8090))# 发文件
# 定制报头
head {filepath:rH:\python\day32,filename:r05 python fullstack s9day32 strcuct模块定制报头的理论.mp4,filesize:None}
file_path os.path.join(head[filepath],head[filename])
file_size os.path.getsize(filepath)
head[filesize] file_sizejson_head json.dumps(head) # 字典转成字符串
bytes_head json_head.encode(utf-8) # 字符串转bytes类型
head_len len(bytes_head) # 报头的长度
pack_len struct.pack(i, head_len) # 报头长度转成固定的4字节长度sk.send(pack_len) # 先发报头长度
sk.send(bytes_head) # 再发报头内容
# 然后再发文件内容
buffer 1024
with open(filepath, rb) as f:while file_size:if file_size buffer:content f.read(buffer)sk.send(content)file_size - bufferelse:content f.read(file_size)sk.send(content)break
sk.close 服务端 import socket
import os
import json
import structsk socket.socket()
sk.bind((127.0.0.1,8090))
sk.listen()conn, addr sk.accept()
# 接收
head_len conn.recv(4) # 接收报头长度
head_len struct.unpack(i, head_len)[0] # 解包成元组 第一个
json_head conn.recv(head_len).decode(utf-8)
head json.loads(json_head) # 报头filesize head[filesize]
buffer 1024
# 写入文件
with open(head[filename], wb) as f:while filesize:if filesize buffer:content conn.recv(buffer)f.write(content)filesize - bufferelse:f.write(conn.recv(filesize))breakconn.close
sk.close 转载于:https://www.cnblogs.com/happyfan/p/10450905.html