• tcp协议传输中的粘包问题


    什么是粘包问题

      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()
    
    
    
    折叠

  • 相关阅读:
    只是因为上了那个网站,就被公安局没收百万财产!
    ubuntu 20.04 访问csdn报错 Secure connection failed
    【SpringBoot应用篇】SpringBoot集成Caffeine本地缓存
    MybatisPlus
    Linux 小程序-进度条
    腾讯云服务器多少钱一年?腾讯云优惠服务器有哪些?
    centos docker服务问题
    制造企业MES管理系统解决方案的深化应用
    阿里云数据库RDS有哪些?细数关系型数据库大全
    金仓数据库KingbaseES服务器应用参考手册--11. sys_upgrade
  • 原文地址:https://www.cnblogs.com/Maxs-message/p/16535788.html