• 注册
当前位置:1313e > 默认分类 >正文

解决数据传输粘包的问题

解决数据传输粘包的问题

服务端

将数据分为6个阶段发送给客户端

  1. 将报头内容,制作成字典形式
  2. 将字典dumps为json字符串
  3. 把得到的json字符串,转换为二进制bytes
  4. 通过struct.pack把二进制bytes的json字符串计算出4个字节长度
  5. 发送报头 4个字节长度
  6. 发送数据
import socket
import subprocess
import struct
import jsonphone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)  # 在bing 之前添加; 用于端口重用,释放phone.bind(("127.0.0.1",8080))phone.listen(5)print("server start....")# 接收消息,和发送消息
while True:conn,client_addr=phone.accept()     # 重新建立连接while True:try:cmd = conn.recv(1024)print("客户端接收:",cmd.decode("utf-8"))if not cmd:break                            # 针对linux 客户端如果断开后,服务端持续打印空res = subprocess.Popen(cmd.decode("utf-8"),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)stdout = res.stdout.read()stderr = res.stderr.read()# 制作报头# header = struct.pack("i",len(stdout)+len(stderr))       # i 表示把长度打包成 4个 字节长度header_dic = {"total_size":len(stdout)+len(stderr),"md5":None}header_json = json.dumps(header_dic)header_bytes = header_json.encode("utf-8")# 先把报头的长度 打包成 4个 字节长度 发送给客户端conn.send(struct.pack("i",len(header_bytes)))# 发送报头conn.send(header_bytes)conn.send(stderr)conn.send(stdout)except Exception:                               # 针对windows 如果客户端断开,服务端也断开breakconn.close()
phone.close()

客户端

客户端接收数据

  1. 接收报头长度为struct.pack“i”大小为4个字节,固定长度
  2. 解析报头,取出真正数据报头的长度
  3. 根据数据报头的长度收取bytes字符串长度
  4. 提取报头字典
  5. 从字典中取出,数据的大小
  6. 循环接收数据

import socket
import struct
import jsonphone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.connect(("127.0.0.1",8080))# phone.send("hello".encode("utf-8"))
while True:cmd = input(">>:").strip()if not cmd:continuephone.send(cmd.encode("utf-8"))# 接收报头长度,大小为 “i” 定义的4个字节struct_res = phone.recv(4)# 解析报头,取出报头长度header_size = struct.unpack("i",struct_res)[0]# 在收报头header_bytes = phone.recv(header_size)# 提取报头字典head_json = header_bytes.decode("utf-8")head_dic = json.loads(head_json)# 取出loads后字典中的total_size的值total_size = head_dic["total_size"]# 根据 取出的 字符串长度,循环接收内容recv_size = 0                               # 初始接收字节数为空data = b""                                  # 初始数据值为空while recv_size < total_size:recv_date = phone.recv(1024)recv_size += len(recv_date)data += recv_dateprint("命令结果:", data.decode("gbk"))phone.close()

转载于:https://www.cnblogs.com/baolin2200/p/7415360.html

本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 162202241@qq.com 举报,一经查实,本站将立刻删除。

最新评论

欢迎您发表评论:

请登录之后再进行评论

登录