粘包问题

粘包问题

返回首页

粘包问题:是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一个TCP段,若连续几次需要send的数据都很少,通常TCP会根据优化算法把这些数据合成一个TCP段后一次发出,这样接收方就收到了粘包数据。使用的算法是Nagle。

TCP协议是流式传输,没有开始没有结束,所以也就不知道在哪里分开粘结点。

自制报头解决粘包问题:

报头:固定长度、包含对将要发送的数据添加描述信息。

 client端:

import socket
import struct
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ip_port = ('127.0.0.1', 8081)
phone.connect(ip_port)

# 通信循环
while True:
    # 发消息
    cmd = input('>>: ').strip()
    if not cmd: continue
    phone.send(bytes(cmd, encoding='utf-8'))

    # 收报头 收4个字节
    baotou=phone.recv(4)
    # 定义的i的报头长度,用unpack去解报头,第0个是数据长度
    data_size=struct.unpack('i',baotou)[0]

    # 收数据,
    recv_size=0
    recv_data=b''
    while recv_size < data_size:
        data=phone.recv(1024)
        recv_size+=len(data)
        recv_data+=data

    print(recv_data.decode('utf-8'))

phone.close()

Server端:

#coding:utf-8
import socket
import struct
import subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip_port=('127.0.0.1',8081)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(ip_port)
phone.listen(5)

#链接循环
while True:
    conn,addr=phone.accept()
    print('client addr',addr)
    #通讯循环
    while True:
        try:
            cmd=conn.recv(1024)
            res=subprocess.Popen(cmd.decode('utf-8'),
                             shell=True,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
            out_res=res.stdout.read()
            err_res=res.stderr.read()
            # 发送报头部分
            data_size=len(out_res)+len(err_res)
            # 发送数据部分,定义报头长度为4个字节
            conn.send(struct.pack('i',data_size)) #struck.pack是打包,i是代表4个字节
            conn.send(out_res)
            conn.send(err_res)

        except Exception:
            break

    conn.close()
phone.close()

------- END ------

原文地址:https://www.cnblogs.com/george92/p/14890212.html