zoukankan      html  css  js  c++  java
  • Python------网络编程2

    1. 黏包现象.

      • 系统缓冲区:用户或服务端接收信息与传输介质之间的媒介。
      • 缓冲区的作用:防止网络出现短暂的异常或波动而对计算机传输数据带来的直接影响。
        • Remark:缓冲区解决了上传下载的传输效率的问题,带来了黏包问题。
    2. 系统缓冲区.

      缓冲区的作用?

      没有缓冲区:如果你的网络出现短暂的异常或者波动,接收数据就会出现短暂的中断,影响你的下载或者上传的效率.

      但是 凡是都是双刃剑,缓冲区解决了上传下载的传输效率的问题,带来了黏包问题.

    3. 什么情况下产生黏包

      1. recv会产生黏包(如果recv接受的数据量(1024)小于发送的数据量,第一次只能接收规定的数据量1024,第二次接收剩余的数据量)
      2. send 也可能发生粘包现象.(连续send少量的数据发到输出缓冲区,由于缓冲区的机制,也可能在缓冲区中不断积压,多次写入的数据被一次性发送到网络)
    4. 解决黏包的方案

    low版

    server

    import socket
    import subprocess
    import struct
    phone = socket.socket()
    phone.bind(('127.0.0.1', 8888))
    phone.listen(5)
    # 4. 接收连接
    print('start')
    conn, addr = phone.accept()
    while 1:
        try:
            cmd = conn.recv(1024)
            obj = subprocess.Popen(cmd.decode('utf-8'),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE,
                                   )
            result = obj.stdout.read() + obj.stderr.read()
            # print(f'服务端发送的总字节数{len(result)}')
            # 1. 制作报头
            total_size = len(result)
            # 2. 将不固定长度的int类型的报头,转化成固定长度bytes 4个字节
            # 将一个数字转化成等长度的bytes类型。
            total_size_bytes = struct.pack('i', total_size)
            # 3. 发送报头
            conn.send(total_size_bytes)
            # 4. 发送原数据
            conn.send(result)
        except ConnectionResetError:
            break
    conn.close()
    phone.close()
    
    

    client

    import socket
    import struct
    phone = socket.socket()
    phone.connect(('127.0.0.1', 8888))
    # 发消息
    while 1:
        cmd = input('>>>').strip()
        phone.send(cmd.encode('utf-8'))
        # 1. 接收报头
        head_bytes = phone.recv(4)
        # 2. 将报头反解回int类型
        total_size = struct.unpack('i', head_bytes)[0]  # 1517
        # 3. 循环接收原数据
        total_data = b''
        while len(total_data) < total_size:
            total_data += phone.recv(1024)
        print(total_data.decode('gbk'))
    # 关机
    phone.close()
    
    
    

    旗舰版

    server

    import socket
    import subprocess
    import struct
    import json
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    phone.bind(('127.0.0.1', 8878))
    phone.listen(5)
    while 1:
        conn, client_addr = phone.accept()
        print(client_addr)
        while 1:
            try:
                cmd = conn.recv(1024)
                ret = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                correct_msg = ret.stdout.read()
                error_msg = ret.stderr.read()
                # 1 制作固定报头
                total_size = len(correct_msg) + len(error_msg)
                header_dict = {
                    'md5': 'fdsaf2143254f',
                    'file_name': 'f1.txt',
                    'total_size': total_size,
                }
                header_dict_json = json.dumps(header_dict)  # str
                bytes_headers = header_dict_json.encode('utf-8')
                header_size = len(bytes_headers)
                header = struct.pack('i', header_size)
                # 2 发送报头长度
                conn.send(header)
                # 3 发送报头
                conn.send(bytes_headers)
                # 4 发送真实数据:
                conn.send(correct_msg)
                conn.send(error_msg)
            except ConnectionResetError:
                break
    conn.close()
    phone.close()
    

    client

    import socket
    import struct
    import json
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    phone.connect(('127.0.0.1', 8878))
    while 1:
        cmd = input('>>>').strip()
        if not cmd: continue
        phone.send(cmd.encode('utf-8'))
        # 1,接收固定报头
        header_size = struct.unpack('i', phone.recv(4))[0]
        # 2,解析报头长度
        header_bytes = phone.recv(header_size)
        header_dict = json.loads(header_bytes.decode('utf-8'))
        # 3,收取报头
        total_size = header_dict['total_size']
        # 3,根据报头信息,接收真实数据
        recv_size = 0
        res = b''
        while recv_size < total_size:
            recv_data = phone.recv(1024)
            res += recv_data
            recv_size += len(recv_data)
        print(res.decode('gbk'))
    phone.close()
    
  • 相关阅读:
    linux脚本启动停止一个jar
    如何突破各种防火墙的防护 [转]
    linux查看端口占用
    网页标题图标添加
    Go语言的一些使用心得
    kubernetes系列之ConfigMap使用方式
    Kubernetes因限制内存配置引发的错误
    Kubernetes系列之理解K8s Service的几种模式
    kubernetes中的Pause容器如何理解?
    Kubernetes系列之Helm介绍篇
  • 原文地址:https://www.cnblogs.com/hql1117/p/11201832.html
Copyright © 2011-2022 走看看