zoukankan      html  css  js  c++  java
  • 基于ssh实现远程执行命令:解决粘包问题终极版

    # 服务端必须满足至少三点:
    # 1. 绑定一个固定的ip和port
    # 2. 一直对外提供服务,稳定运行
    # 3. 能够支持并发

    解决粘包问题的大致思路解决方法:
      首先制作报头
      先获取报头的长度,然后将报头的长度利用struct 模块pack 转化成固定长度的字符串发过去
      对方接收这个固定长度的编码,利用struct 模块 unpack获取报头的长度,然后再接收这个报头的长度,得到报头
      得到报头之后再破解报头中的信息,得到正文的长度格式等具体的信息,如果很大,就用一个循环不断的接收和拼接这个正文,
      最终获取到正文



    ###服务端程序


    from socket import *
    import subprocess
    import struct
    import json

    server = socket(AF_INET, SOCK_STREAM)
    server.bind(('127.0.0.1', 8081))
    server.listen(5)

    # 链接循环
    while True:
    conn, client_addr = server.accept()
    print(client_addr)

    # 通信循环
    while True:
    try:
    cmd = conn.recv(1024) # cmd=b'dir'
    if len(cmd) == 0: break # 针对linux系统
    obj = subprocess.Popen(cmd.decode('utf-8'),
    shell=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
    )
    stdout = obj.stdout.read()
    stderr = obj.stderr.read()
    # 1. 先制作报头
    header_dic = {
    'filename': 'a.txt',
    'md5': 'asdfasdf123123x1',
    'total_size': len(stdout) + len(stderr)
    }
    header_json = json.dumps(header_dic)
    header_bytes = header_json.encode('utf-8')

    # 2. 先发送4个bytes(包含报头的长度)
    conn.send(struct.pack('i', len(header_bytes)))
    # 3 再发送报头
    conn.send(header_bytes)

    # 4. 最后发送真实的数据
    conn.send(stdout)
    conn.send(stderr)
    except ConnectionResetError:
    break

    conn.close()

    server.close()


    ##客户端程序

    from socket import *
    import struct
    import json

    client = socket(AF_INET, SOCK_STREAM)
    client.connect(('127.0.0.1', 8081))

    # 通信循环
    while True:
    cmd = input('>>: ').strip()
    if len(cmd) == 0: continue
    client.send(cmd.encode('utf-8'))
    # 1. 先收4bytes,解出报头的长度
    header_size = struct.unpack('i', client.recv(4))[0]

    # 2. 再接收报头,拿到header_dic
    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. 接收真正的数据
    cmd_res = b''
    recv_size = 0
    while recv_size < total_size:
    data = client.recv(1024)
    recv_size += len(data)
    cmd_res += data

    print(cmd_res.decode('gbk'))

    client.close()

  • 相关阅读:
    windows搭建golang环境
    Python 爬虫入门(一)环境搭建
    后端——框架——测试框架——junit——条件
    后端——框架——测试框架——junit——运行(程序方式)
    后端——框架——测试框架——junit——元信息
    后端——框架——测试框架——junit——扩展功能
    小说——鬼吹灯——我的背景
    后端——框架——测试框架——junit——工具类
    后端——框架——测试框架——junit——初篇
    后端——框架——测试框架——junit——测试案例
  • 原文地址:https://www.cnblogs.com/1832921tongjieducn/p/11352573.html
Copyright © 2011-2022 走看看