zoukankan      html  css  js  c++  java
  • 32、黏包的解决方式、struct模块

    黏包的解决方式

      黏包出现的根本原因是接收方不知道要传过来多少数据,解决方法1:在传给接收方以前告诉它要传过去多少数据。  解决方法2:使用struct方法

    解决方法1:传之前告诉它要传多少

    #服务器端
    import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1',8080))
    sk.listen()
    conn,addr = sk.accept()
    while True:
        cmd = input('>>>')
        if cmd == 'q':
            conn.send(b'q')
            break
        conn.send(cmd.encode('gbk'))
        num = conn.recv(1024).decode('utf-8')  # 2048
        conn.send(b'ok')
        res = conn.recv(int(num)).decode('gbk')
        print(res)
    conn.close()
    sk.close()
    #客户端
    import socket
    import subprocess
    
    sk = socket.socket()
    sk.connect(('127.0.0.1',8080))
    while True:
        cmd = sk.recv(1024).decode('gbk')
        if cmd == 'q':
            break
        res = subprocess.Popen(cmd,shell=True,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
        std_out = res.stdout.read()
        std_err = res.stderr.read()
        sk.send(str(len(std_out)+len(std_err)).encode('utf-8'))   #2000
        sk.recv(1024)   # ok
        sk.send(std_out)
        sk.send(std_err)
    sk.close()

    这种方法的好处:确定了我要接收多大的值

      1)要在文件中配置一个配置项:就是每一次recv的大小

      2)当我们要发送大数据的时候,要明确的告诉接收方要发送多大的数据,以便接收方能够准确接收所有的数据。

      3)用处:多用在文件传输的过程中

        1、大文件的传输一定是按照字节读,每一次读固定的字节

        2、传输的过程中,一边读一边传,接收端一边收一边写

        3、send这个大文件之前,每一次文件总量减去固定值

        4、recv这个大文件,每一次接收之后减去固定值

    这种方法的不好的地方:多了一次交互

      1)sendsendto,在超过一定范围的时候就会报错

      2)程序的内存管理(啥意思???

    解决方法二:用struct将文件大小或者长度转化成4个字节的bytes类型

    import socket
    import subprocess
    import struct   #接收命令
    sk=socket.socket()
    sk.connect(('127.0.0.1',8008))
    while True:
        cmd=sk.recv(1024).decode('gbk')
        ret=subprocess.Popen(cmd,shell=True,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
        std_out=ret.stdout.read()
        std_err=ret.stderr.read()
        len_std=len(st_out)+len(std_err)
        len_num=struct.pack('i',len_std)  #将执行命令后的内容长度转化成4个字节类型
        sk.send(len_num)
        sk.send(std_out)
        sk.send(std_err)
    
    sk.close()
    #客户端
    import socket
    import struct
    sk=socket.socket()
    sk.bind(('127.0.0.1',8008))
    sk.listen()
    con,addr=sk.accept()
    while True:
        cmd=input('>>>')
        con.send(cmd.encode('gbk'))
        num=con.recv(4)
        len_by=struct.unpack('i',num)[0]  #接收到的4个字节长度转化成数字,重点!!!
        ret=con.recv(len_by).decode('gbk')
        print(ret)
    con.close()
    sk.close()
  • 相关阅读:
    Docker 制作定制asp.netcore 的容器
    Windows docker k8s asp.net core
    Ubuntu 18 Kubernetes集群的安装和部署 以及Helm的安装
    ubuntu 18 docker 搭建Prometheus+Grafana
    ubuntn18 docker zabbix+grafana安装和使用
    .net Core MongoDB用法演示
    Ubuntu18 安装搭建Harbor
    ubuntu docker inflxudb(安装 使用 备份 还原 以及python编码) telegraf Grafana
    python selenium爬虫工具
    python selenium IE Firxfor pyinstaller
  • 原文地址:https://www.cnblogs.com/wangyuxing/p/8379416.html
Copyright © 2011-2022 走看看