解决粘包问题终极方法

解决粘包问题终极方法

#server粘包
import socket
import subprocess
import struct
soc=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
soc.bind(('127.0.0.1',8001))
soc.listen(3)
while True:
    print('等待客户端连接')
    conn,addr=soc.accept()
    print('有个客户端连接上了',addr)
    while True:
        try:
            data=conn.recv(1024)
            if len(data)==0:
                break
            print(data)
            obj = subprocess.Popen(str(data,encoding='utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            #执行正确的结果 b 格式,gbk编码(windows平台)
            msg=obj.stdout.read()

            #发送的时候需要先把长度计算出来
            #头必须是固定长度
            #先发4位,头的长度
            import json
            dic={'size':len(msg)}
            dic_bytes=(json.dumps(dic)).encode('utf-8')
            #head_count是4个字节的长度
            head_count=struct.pack('i',len(dic_bytes))
            print(dic)
            conn.send(head_count)
            #发送头部内容
            conn.send(dic_bytes)
            #发了内容
            conn.send(msg)
        except Exception:

            break
    # 关闭通道
    conn.close()


# 关闭套接字
soc.close()
#client模块
import socket
import struct
import json
soc=socket.socket()

soc.connect(('127.0.0.1',8001))
while True:
    in_s=input('请输入要执行的命令:')
    soc.send(in_s.encode('utf-8'))
    #头部字典的长度
    head_dic_len=soc.recv(4)
    #解出真正的长度
    head_l=struct.unpack('i',head_dic_len)[0]
    #byte 字典的长度
    #收真正的头部字典
    dic_byte=soc.recv(head_l)
    head=json.loads(dic_byte)
    print(head)
    l=head['size']
    count=0
    data_total=b''
    print(l)
    while count<l:
        if l<1024: #如果接受的数据小于1024 ,直接接受数据大小
            data=soc.recv(l)
        else:#如果接受的数据大于1024
            if l-count>=1024: #总数据长度-count(目前收到多少,count就是多少) 如果还大于1024  ,在收1024
                data=soc.recv(1024)
            else: #总数据长度-count(目前收到多少,count就是多少) 如果小于1024,只收剩下的部分就可
                data=soc.recv(l-count)

        data_total+=data
        count+=len(data)

    print(str(data_total,encoding='gbk'))

转载于:https://www.cnblogs.com/aden668/p/11478436.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
.版本 2 .支持库 spec .支持库 sock .程序集 窗口程序集_启动窗口 .子程序 _按钮2_被单击 客户1.发送数据 (取重复字节集 (10000, 到字节集 (“1”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (20000, 到字节集 (“2”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (30000, 到字节集 (“3”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (40000, 到字节集 (“4”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (50000, 到字节集 (“5”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (60000, 到字节集 (“6”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (70000, 到字节集 (“7”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (80000, 到字节集 (“8”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (90000, 到字节集 (“9”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (100000, 到字节集 (“0”)) + 到字节集 (“结尾符”)) .子程序 _服务器1_数据到达 .局部变量 取回数据, 字节集 .局部变量 数据数组, 文本型, , "0" .局部变量 次数, 整数型 .局部变量 临时数据, 字节集, 静态 .局部变量 得到的封包, 文本型 取回数据 = 服务器1.取回数据 () .判断开始 (取字节集右边 (取回数据, 6) ≠ 到字节集 (“结尾符”))  ' 6为结尾符的长度;这里检测封包是否全部发送完毕,如果没有发送完毕就会把发送来的封包数据进行累加     临时数据 = 临时数据 + 取回数据 .默认     临时数据 = 临时数据 + 取回数据  ' 检测到结尾符出现,说明数据已经发送完毕,这里把最后发送来的带有结尾符的数据加上就OK了。     临时数据 = 子字节集替换 (临时数据, 到字节集 (“结尾符”), , 取字节集长度 (临时数据) - 6, 6)  ' 6为结尾符的长度;这里把结尾符替换尾空,剩余数据尾完整的纯净数据。     数据数组 = 分割文本 (到文本 (临时数据), “分隔符”, )  ' 这里把收到的数据进行分割处理,无论服务器发送了多少次,都统一按分隔符分割     调试输出 (“封包数量:” + 到文本 (取数组成员数 (数据数组)))     .计次循环首 (取数组成员数 (数据数组), 次数)         得到的封包 = 数据数组 [次数]  ' 这里得到分割后的封包文本。         调试输出 (“第” + 到文本 (次数) + “个封包的大小:” + 到文本 (取文本长度 (得到的封包)))  ' 这里的大小和上面发送封包的大小相同,可以看到封包的分割次数。     .计次循环尾 ()     临时数据 = {  } .判断结束 .子程序 __启动窗口_创建完毕 客户1.连接 (取本机名 (), 8888)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值