python入门开发学习笔记之粘包现象与解决方案
发布日期:2025-05-13 01:17:47 浏览次数:2 分类:精选文章

本文共 3637 字,大约阅读时间需要 12 分钟。

粘包问题及其解决方案

粘包问题(Glue Problem)在网络通信中是一个常见的现象,尤其是在使用TCP协议进行通信时。粘包问题的核心在于接收端接收到的数据并非完整的消息片段,而是部分或全部消息的数据片段与前后消息的数据混合在一起。这一问题的出现主要源于TCP协议的面向流特性,使得消息的边界信息不明确。

粘包问题的原因

  • TCP的面向流特性:TCP协议将数据视为无结构的字节流,不关心数据的边界。发送方可能将多个小数据块合并成一个大数据块发送给接收方,而接收方也可能不以固定大小的数据块来读取数据,这导致消息片段被混合。

  • 缓冲区处理:发送方和接收方都有自己的缓冲区,数据在传输过程中会被临时存储,可能导致部分数据被拆分或混合。

  • Nagle算法:TCP协议为了提高传输效率,使用Nagle算法将多个小数据块合并成一个大数据块发送。如果连续发送的数据块间隔较小,Nagle算法会将它们合并成一个TCP段。

  • 粘包问题的解决方法

  • 明确消息边界

    • 消息头:在消息前发送一个包含消息长度的消息头,通知接收方下一次将要发送的数据量。
    • 消息体:接收方在已知消息长度后,继续读取数据,直到读取完所有数据为止。
  • 自定义报头

    • 使用结构化数据序列化技术(如JSON或XML),并加上自定义报头,包含消息类型、长度和其他元数据信息。
    • 例如,发送方先发送一个报头,包含消息长度和元数据,接收方根据报头信息读取完整的消息数据。
  • 优化数据传输策略

    • 合理设置接收缓冲区大小,避免数据片段被拆分。
    • 使用高效的数据传输协议或机制,减少数据拆分和粘包的可能性。
  • 应用层协议设计

    • 在应用层定义明确的消息协议,规定消息的格式和边界,确保发送方和接收方能够正确解析数据。
  • 优化方法示例

    普通青年版

    • 服务器端:
      import socket, subprocess
      ip_port = ('127.0.0.1', 8080)
      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
      s.bind(ip_port)
      s.listen(5)
      while True:
      conn, addr = s.accept()
      print('客户端', addr)
      while True:
      cmd = conn.recv(1024)
      if not cmd:
      break
      res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
      stderr = res.stderr.read()
      stdout = res.stdout.read()
      data_length = len(stdout)
      conn.send(str(data_length).encode('utf-8'))
      data = conn.recv(1024).decode('utf-8')
      if data == 'recv_ready':
      conn.sendall(stdout)
      conn.close()
    • 客户端:
      import socket
      ip_port = ('127.0.0.1', 8080)
      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      res = s.connect_ex(ip_port)
      while True:
      msg = input('> : ').strip()
      if len(msg) == 0:
      continue
      if msg == 'quit':
      break
      s.send(msg.encode('utf-8'))
      length = int(s.recv(1024).decode('utf-8'))
      s.send('recv_ready'.encode('utf-8'))
      send_size = 0
      recv_size = 0
      data = b''
      while recv_size < length:
      data += s.recv(1024)
      recv_size = len(data)
      print(data.decode('utf-8'), end='')

    文艺青年版二

    • 服务器端:
      import socket, struct, json
      ip_port = ('127.0.0.1', 8080)
      phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
      phone.bind(ip_port)
      phone.listen(5)
      while True:
      conn, addr = phone.accept()
      while True:
      cmd = conn.recv(1024)
      if not cmd:
      break
      res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
      err = res.stderr.read()
      stdout = res.stdout.read()
      back_msg = err if err else stdout
      headers = {'data_size': len(back_msg)}
      head_json = json.dumps(headers)
      head_json_bytes = bytes(head_json, encoding='utf-8')
      phone.send(struct.pack('i', len(head_json_bytes)))
      phone.send(head_json_bytes)
      phone.sendall(back_msg)
      conn.close()
    • 客户端:
      from socket import *
      import struct, json
      ip_port = ('127.0.0.1', 8080)
      client = socket(AF_INET, SOCK_STREAM)
      client.connect(ip_port)
      while True:
      cmd = input('> : ').strip()
      if not cmd:
      continue
      if cmd == 'quit':
      break
      client.send(bytes(cmd, encoding='utf-8'))
      head = client.recv(4)
      head_json_len = struct.unpack('i', head)[0]
      head_json = json.loads(client.recv(head_json_len).decode('utf-8'))
      data_len = head_json['data_size']
      recv_size = 0
      recv_data = b''
      while recv_size < data_len:
      recv_data += client.recv(1024)
      recv_size = len(recv_data)
      print(recv_data.decode('utf-8'), end='')

    总结

    粘包问题源于TCP协议的面向流特性,解决方法包括明确消息边界、使用自定义报头、优化数据传输策略等。选择具体方法需根据应用场景和性能需求综合考量。

    上一篇:python入门开发学习笔记之绑定方法与非绑定方法
    下一篇:python入门开发学习笔记之粘包现象与解决方案

    发表评论

    最新留言

    路过,博主的博客真漂亮。。
    [***.116.15.85]2025年05月12日 21时04分37秒

    关于作者

        喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
    -- 愿君每日到此一游!

    推荐文章

    2025版万字长文入门大语言模型(LLM)零基础入门到精通,收藏这篇就够了 2023-01-25
    2025版最新0基础怎么转行网络安全?零基础入门到精通,收藏这篇就够了 2023-01-25
    2025版最新Bash Shell入门指南,零基础入门到精通,收藏这篇就够了 2023-01-25
    2025版最新C++快速入门(适合小白)零基础入门到精通,收藏这篇就够了 2023-01-25
    2025版最新一文彻底搞懂大模型 - Agent(非常详细)零基础入门到精通,收藏这篇就够了 2023-01-25
    2025版最新关于HW护网行动的一些知识,零基础入门到精通,收藏这篇就够了 2023-01-25
    2025版最新大模型学习路线,零基础入门到精通,收藏这篇就够了 2023-01-25
    2025版最新大模型开发流程(非常详细)零基础入门到精通,收藏这一篇就够了 2023-01-25
    2025版最新大模型微调方法(非常详细)零基础入门到精通,收藏这篇就够了 2023-01-25
    2025版最新大语言模型的指令微调,零基础入门到精通,收藏这篇就够了 2023-01-25
    2025版最新小白学习大模型:什么是大模型?零基础入门到精通,收藏这篇就够了 2023-01-25
    2025版最新常用黑客工具之【Nmap 教程基础】零基础入门到精通,收藏这篇就够了 2023-01-25
    2025版最新渗透测试和黑客工具列表,零基础入门到精通,收藏这一篇就够了 2023-01-25
    2025版最新网络安全等级保护测评指南,零基础入门到精通,收藏这篇就够了 2023-01-25
    2025版最新运维怎么转行网络安全?零基础入门到精通,收藏这篇就够了 2023-01-25
    2025版最新黑客学习网站(非常详细),零基础入门到精通,看这一篇就够了 2023-01-25
    2025版网络工程11个高含金量证书(非常详细)零基础入门到精通,收藏这篇就够了 2023-01-25
    2025自学成为黑客必读的5本书籍,带你从小白进阶成大佬 2023-01-25
    23张图告诉你组建一个网络需要用到哪些硬件设备?路由器、交换机、防火墙是不是就够了? 2023-01-25
    #12 btrfs文件系统 2023-01-25