Python socket粘包问题(初级解决办法)

server端配置:

import socket,subprocess,struct
from   socket import *
server=socket(AF_INET,SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
    conn,client_addr=server.accept()
    while True:
        try:
            cmd=conn.recv(1024)
            if len(cmd) == 0:break
            obj=subprocess.Popen(
                cmd.decode('utf-8'),
                shell=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
            )
            out=obj.stdout.read()  #bytes类型
            err=obj.stderr.read()
            print(len(out+err))

            # 解决粘包问题的步骤,先发型数据的长度
            total_size=len(out)+len(err)  #数据类型,1.变为bytes类型 2.还是个固定长度

            #1.制作固定长度的包头
            header=struct.pack('i',total_size)

            #2.发送报头
            conn.send(header)

            #固定数据报的head头的大小(自定义数据)

            #下面是发送真是的数据
            # conn.send(out+err)
            #2个包是一起发过去的,因为间隔短
            conn.send(out)
            conn.send(err)

            #发过去的整体是一个数据报=报头+数据部分


        except ConnectionResetError:
            break
    conn.close()

server.close()

 

client端配置:

import socket
import socket,struct
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('127.0.0.1',8080))
while True:
    cmd=input('输入执行的命令:')
    if len(cmd) == 0: continue
    client.send(cmd.encode('utf-8'))
    #1.先收固定长度的的包头默认stuck就是固定了长度为4
    header=client.recv(4)    #第二次再收不是下一个包头,是上次命令的残留
    #2.解析包头
    total_size=struct.unpack('i',header)[0]  #拿到的是个元祖,元祖的0就是这个长度值
    print(total_size)
    #3.根据包头内的信息,收取真实数据
    # client.recv(total_size)   因为现实数据量太大的时候就不行,所以考虑while循环

    #思考如果数据大,total_size数据会特别大就会直接报错
    #为了解决输入较大程序,定义一个小的变量,循环一点点就去收
    recv_size=0
    res=b''
    while recv_size < total_size:
        recv_data=client.recv(1024)  #recv_data是bytes类型,是唯一真实的值,有多少就会收多少
        res+=recv_data
        recv_size+=len(recv_data)

    print(res.decode('gbk'))


client.close()

 

posted @ 2018-07-08 21:23  yangzhizong  阅读(173)  评论(0编辑  收藏  举报