Python3之优化版粘包解决问题

服务端

import json
import socket
import struct
import subprocess

phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
phone.bind(('127.0.0.1', 8080))

phone.listen(5)
while 1:
    conn, addr = phone.accept()
    while 1:
        try:

            data = conn.recv(1024)
            print(data)
            res = subprocess.Popen(data.decode('utf-8'), shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
            stdout = res.stdout.read()
            stderr = res.stderr.read()
            # 定制报头
            header_dict = {
                'total_size': len(stdout) + len(stderr),
                'filename': None
            }
            header_bytes = json.dumps(header_dict).encode('utf-8')
            # 发送报头长度
            header_len = struct.pack('i', len(header_bytes))
            conn.send(header_len)
            # 发送报头
            conn.send(header_bytes)
            conn.send(res)
            # 发送数据部分
            conn.send(stdout)
            conn.send(stderr)

        except Exception:
            break
    conn.close()
phone.close()

客户端

import json
import socket
import struct

phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8080))

while 1:
    cmd = input('请输入>>:').strip()
    if not cmd: continue
    phone.send(cmd.encode('utf-8'))

    # 接收报头长度
    res = phone.recv(4)
    # 对报头长度解压
    header_size = struct.unpack('i', res)[0]
    # 接收报头长度的内容
    header_bytes = phone.recv(header_size).decode('utf-8')
    # 对报头字典进行反序列化
    header_json = json.load(header_bytes)
    # 获取数据长度
    data_size = header_json['total_size']

    # 根据报头数据长度对数据进行接收
    recv_size = 0
    total_data = b''
    while recv_size < data_size:
        data_recv = phone.recv(1024)
        if (data_size - len(data_recv)) < 1024:
            left_data = phone.recv(data_size - len(data_recv))
            total_data += left_data
        total_data += data_recv
        recv_size += len(data_recv)

    print(total_data.decode('gbk'))

phone.close()

大体思路就是服务端将报头信息进行优化,对要发送的内容用字典进行描述,首先字典不能直接进行网络传输,需要进行序列化转成json格式字符串,然后转成bytes格式服务端进行发送,因为bytes格式的json字符串长度不是固定的,所以要用struct模块把bytes格式的json字符串长度压缩成固定长度,发送给客户端。客户端进行接收,反解就会得到完整的数据包。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值