粘包问题和struck解决

本文介绍Python网络编程中如何使用struct模块处理报头信息,并通过客户端和服务端实例展示如何有效解决TCP粘包问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:struct模块的使用

import struct
import json
header_dic={
 'filename':'a.txt',
    'total_size':11112313123212222222222222222222222222222222222222222222222222222221111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111131222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222223,
    'hash':'asdf123123x123213x'
} #定义报头,字典格式,报头里面可以存储各种需要的信息
header_json=json.dumps(header_dic)
#将报头序列化,得到一个json字符串
header_bytes=header_json.encode('utf-8')
#得到json的二进制格式

obj=struct.pack('i',len(header_bytes))#将整形数字打包成字节格式

#打包成二进制字典长度,发送给客户端

print(obj,len(obj))
# res=struct.unpack('i',header)#解包,是元祖形式,第一个是字节串长度

# print(res[0])

二:解决粘包问题



1, 服务端

from socket import *
import subprocess
import struct
import json
server=socket(AF_INET,SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)
while True:
    conn,client_addr=server.accept()
    print('新的客户端',client_addr)
    while True:
        try:
            cmd=conn.recv(1024) #cmd=b'dir'
            if len(cmd) == 0:break
            # 运行系统命令
            obj=subprocess.Popen(cmd.decode('utf-8'),
                             shell=True,
                             stderr=subprocess.PIPE,
                             stdout=subprocess.PIPE
                             )
            stdout=obj.stdout.read()
            stderr=obj.stderr.read()
            #先制作报头
            header_dic={
                'filename':'a.txt',
                'total_size':len(stdout) + len(stderr),
                'hash':'xasf123213123'
            }
            header_json=json.dumps(header_dic)
            header_bytes=header_json.encode('utf-8')
            #1、先把报头的长度len(header_bytes)打包成4个bytes,然后发送
            conn.send(struct.pack('i',len(header_bytes)))
            #2、发送报头
            conn.send(header_bytes)
            #3、再发送真实的数据
            conn.send(stdout)
            conn.send(stderr)#用加号发送系哦啊率不高,最好发两次比较好
        except ConnectionResetError:
            break

    conn.close()

2,客户端

from socket import *
import struct
import json
client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))
while True:
    cmd=input('>>: ').strip()
    if len(cmd) == 0:continue
    client.send(cmd.encode('utf-8'))
    #1、先收4个字节,该4个字节中包含报头的长度
    header_len=struct.unpack('i',client.recv(4))[0]
    #2、再接收报头
    header_bytes=client.recv(header_len)
    #从报头中解析出想要的内容
    header_json=header_bytes.decode('utf-8')
    header_dic=json.loads(header_json)
    print(header_dic)
    total_size=header_dic['total_size']
    #3、再收真实的数据
    recv_size=0
    res=b''
    while recv_size < total_size :
        data=client.recv(1024)
        res+=data
        recv_size+=len(data)

    print(res.decode('gbk'))


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值