• day 30 粘包 自定义报头


    一、上节回顾:

    1、网络=物理连接介质+互联网协议

    2、OSI七层:应、表、会、传(tcp/udp),网(IP),数(ethernet),物

    3、Tep三次握手建立连接,四次挥手断开连接

       connet()————>accept()

    4、ip+port:标识全世界范围内独一无二的一个应用程序

      server.bind((ip,port))

    5、C/S

      Client:ip+port会随意变

      Server:

        一定要绑定ip+port

        应该支持并发连接

        服务端一旦开启一直运行到世界末日

    二、今日内容:

     坑:reve(1024)

    粘包问题:自定义应用层协议

    TCP:流式协议

    1、 操作命令:

      (1)dir   查看当前文件夹下有哪些子文件夹

    (2)tasklist   查看运行的哪些程序:

    (3)管道符: tasklist : findstr  pychar

    (4) ipconfig   查看IP配置  

    2、subprosess  模块

    import subprocess
    obj=subprocess.Popen("dir",shell=True,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE,
                         )
    print(obj.stdout.read().decode("gbk"))
    print(obj.stderr.read().decode("gbk"))

    解析:管道的内容只能取一次(服务端)

    3、粘包现象: TCP的nagle 算法

      只有TCP 才会出现粘包现象(TCP协议是流式协议)

       粘包:把数据量较小并且时间间隔比较短的包合成一个包发送

      “linux:网卡最大 参数单元:1500个字节   (千兆网卡)
      以太网 是物理层上面的 也是*网卡“
      万兆网卡 是光纤模块 (最大参数单元)
      如果超出字节分片发送(以太网协议 的标准)

     4、struct模块

    import struct
    # 帮我们把数字转成固定长度的bytes类型
    res=struct.pack("i",12323)
    print(res,len(res))
    #将bytes 类型转为数字
    res1=struct.unpack("i",res)
    print(res1[0])

    5、json模块:

    import json
    header_dic={
        'md5':'asdfasdfasdfasdfasdfasdf',
        'total_size':11111111111111111111,
        'filename':'a.txt'
     }
    
    header_json=json.dumps(header_dic)
    header_bytes=header_json.encode('utf-8')
    print(len(header_bytes))
    header_size=struct.pack('i',len(header_bytes))
    print(header_size)

    6、流程:

    完整版:

     7、解决粘包问题:

    import subprocess
    import struct
    import json
    from socket import *
    server=socket(AF_INET,SOCK_STREAM)
    server.bind(('127.0.0.1',8090))
    # print(server)
    server.listen(5)
    while True:
        conn,addr=server.accept()
        # print(conn)
        print(addr)
        while True:
            try:
                cmd=conn.recv(8096)
                if not cmd:break #针对linux
    
                #执行命令
                cmd=cmd.decode('utf-8')
                #调用模块,执行命令,并且收集命令的执行结果,而不是打印
                obj = subprocess.Popen(cmd, shell=True,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       )
                stdout=obj.stdout.read()
                stderr=obj.stderr.read()
    
    
                # 1:先制作报头,报头里放:数据大小, md5, 文件
                header_dic = {
                    'total_size':len(stdout)+len(stderr),
                    'md5': 'xxxxxxxxxxxxxxxxxxx',
                    'filename': 'xxxxx',
                    'xxxxx':'123123'
                }
                header_json = json.dumps(header_dic)
                header_bytes = header_json.encode('utf-8')
                header_size = struct.pack('i', len(header_bytes))
    
                # 2: 先发报头的长度
                conn.send(header_size)
    
                # 3:先发报头
                conn.send(header_bytes)
    
                # 4:再发送真实数据
                conn.send(stdout)
                conn.send(stderr)
            except ConnectionResetError:
                break
        conn.close()
    
    server.close()
    服务端
    import struct
    import json
    from socket import *
    
    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8089))
    
    while True:
        cmd=input('>>: ').strip()
        if not cmd:continue
        client.send(cmd.encode('utf-8'))
    
        # 1:先收报头长度
        obj = client.recv(4)
        header_size = struct.unpack('i', obj)[0]
    
        # 2:先收报头,解出报头内容
        header_bytes = client.recv(header_size)
        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:
            recv_data=client.recv(1024)
            res+=recv_data
            recv_size+=len(recv_data)
        print(res.decode('gbk'))
    
    client.close()
    客户端

        

  • 相关阅读:
    统计学方法(t-检验)
    generate的使用verilog
    FPGA的存储方式大全
    matlab函数
    三年后的我-记于2018
    labview学习——用户界面模式
    labview线程相关
    labview状态机
    JS~字符串长度判断,超出进行自动截取(支持中文)
    AngulaJs -- 隔离作用域
  • 原文地址:https://www.cnblogs.com/number1994/p/8126438.html
Copyright © 2020-2023  润新知