• 缓冲区 subprocess 黏包 黏包的解决方案


    缓冲区:  将程序和网络解耦
    输入缓冲区
    输出缓冲区
    print('>>>>', server.getsockopt(SOL_SOCKET, SO_SNDBUF))  查看输出缓冲区大小
    print('>>>>', server.getsockopt(SOL_SOCKET, SO_RCVBUF))  查看输入缓冲区大小
    

     

    import subprocess
    
    sub_obj = subprocess.Popen(
        "dir",          # 系统指令
        shell=True,     # 固定
        stdout=subprocess.PIPE,  # 标准输出 PIPE 管道,保存着指令的执行结果
        stderr=subprocess.PIPE   # 标准错误输出
    )
    

      

    两种黏包现象:
    1 连续的小包可能会被优化算法给组合到一起进行发送
    2 第一次如果发送的数据大小2000B接收端一次性接受大小为1024,这就导致剩下的内容会被下一次recv接收到,导致结果错乱
    解决方案
    方案一:由于双方不知道对方发送数据的长度,导致接收的时候,可能接收不全,或者多接收另外一次发送的信息内容,
    所以在发送真实数据之前,要先发送数据的长度,接收端根据长度来接收后面的真实数据,但是双方有一个交互确认的过程

    方案二:
    Struct模块,
    打包:struct.pack(‘i’,长度)
    解包:struct.unpack(‘i’,字节)
    服务端
    
    import socket
    import subprocess
    import struct
    
    server = socket.socket()
    
    ip_port = ('127.0.0.1', 8001)
    server.bind(ip_port)
    server.listen()
    
    conn, addr = server.accept()
    
    while 1:
        from_client_cmd = conn.recv(1024)
        print(from_client_cmd.decode('utf-8'))
        # 接收到客户端 发送来的系统指令,我服务端通过subprocess模块到服务端自己的系统里面执行这条指令
        sub_obj = subprocess.Popen(
            from_client_cmd.decode('utf-8'),
            shell=True,
            stdout=subprocess.PIPE,  # 正确结果位置
            stderr=subprocess.PIPE   # 错误
        )
        # 从管道里边拿出结果,通过sunprocess.Popen 的实例化对象.stdout.read()方法来获取管道中的结果
        std_msg = sub_obj.stdout.read()
        # 为了解决黏包现象,我们统计了一下消息的长度,先将消息的长度发送给客户端,客户端通过这个长度来接收后面我们要发送的真实数据
        std_msg_len = len(std_msg)
        print('指令的执行结果长度>>>>', len(std_msg))
        msg_lenint_struct = struct.pack('i',std_msg_len)
        conn.send(msg_lenint_struct+std_msg)
    

      

    客户端
    
    import socket
    import struct
    client = socket.socket()
    client.connect(('127.0.0.1', 8001))
    
    while 1:
        cmd = input('请输入指令:')
        # 发送指令
        client.send(cmd.encode('utf-8'))
    
        # 接收数据长度,首先接收4个字节长度的数据,因为这个4个字节是长度
        server_res_len = client.recv(4)
        msg_len = struct.unpack('i', server_res_len)[0]
    
        print('来自服务端的消息长度', msg_len)
        # 通过解包出来的长度,来接收后面的真实数据
        server_cmd_result = client.recv(msg_len)
    
        print(server_cmd_result.decode('gbk'))
    

      



  • 相关阅读:
    scala 基本语法
    HBase架构深度解析
    scala 面向对象之 继承
    探索 ConcurrentHashMap 高并发性的实现机制
    Spark 源码和应用开发环境的构建
    spark内存管理详解
    2020软件工程第一次作业 L
    实验 1:Mininet 源码安装和可视化拓扑工具 L
    代码阅读方法
    生活中的小感悟
  • 原文地址:https://www.cnblogs.com/YangWenYu-6/p/10267394.html
Copyright © 2020-2023  润新知