解决网络编程的粘包问题

# 服务端
import socket
import subprocess
import struct
import json
servers = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
servers.bind(('127.0.0.1', 7777))
servers.listen(10)
print('start settings')
while True:
    """连接循环"""
    conn, adder = servers.accept()
    print('客服端的信息:', adder)
    while True:
        "通信循环"
        try:
            cmd = conn.recv(1024)  # 1收命令
            #  2执行命令的结果丢到管道里面存起来
            obj = subprocess.Popen(cmd.decode('utf-8'), shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
            #  3从管道里面拿出数据
            stdout = obj.stdout.read()
            stderr = obj.stderr.read()
            #  4制作报头
            header_dict = {'filename': 'a.txt',
                           'md5': 'xxxx',
                           'total_size': len(stdout)+len(stderr)}
            #  4.1制作固定长度的报头
            header_json = json.dumps(header_dict)
            header_bytes = header_json.encode('utf-8')
            header_size = struct.pack('i', len(header_bytes))
            # 4.2发送固定长度的报头
            conn.send(header_size)
            # 4.3再发送报头的信息
            conn.send(header_bytes)
            #  5再发送真实的数据
            conn.send(stdout)
            conn.send(stderr)
        except ConnectionResetError:
            break
    conn.close()
servers.close()
 
# 客服端
import struct
import json
import socket
client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
client.connect(('127.0.0.1', 7777))
while True:
    """通信循环"""
    cmd = input('输入要执行的命令:').strip()  # 收命令
    if not cmd:continue
    client.send(cmd.encode('utf-8'))  # 发送命令
    """先收报头的长度"""
    obj = client.recv(4)  # 收固定长度的报头
    header_size = struct.unpack('i', obj)[0]
    """在收报头"""
    header_bytes = client.recv(header_size)
    """再从报头中解析出对真实数据的描叙信息"""
    header_json = header_bytes.decode('utf-8')
    header_dict = json.loads(header_json)
    total_size = header_dict['total_size']
    """再接受真实的数据"""
    recv_size = 0
    recv_data = b''
    while recv_size < total_size:
        result = client.recv(1024)
        recv_size += len(result)
        recv_data += result
    print(recv_data.decode('gbk'))
client.close()
posted @ 2020-02-02 21:10  nick_xm  阅读(116)  评论(0编辑  收藏  举报