python基于socket模拟实现ssh远程执行命令


Posted in Python onDecember 05, 2020

一、subprocess.Popen()

subprocess模块定义了一个类: Popen

类原型:

class subprocess.Popen( args, 
  bufsize = 0, 
  executable = None, 
  stdin = None, 
  stdout = None, 
  stderr = None, 
  preexec_fn = None, 
  close_fds = False, 
  shell = False, 
  cwd = None, 
  env = None, 
  universal_newlines = False, 
  startupinfo = None, 
  creationflags = 0)

我们只需要关注其中几个参数:

  • args:

args参数。可以是一个字符串,可以是一个包含程序参数的列表。要执行的程序一般就是这个列表的第一项,或者是字符串本身。

  • shell=True:

在Linux下,当shell=True时,如果arg是个字符串,就使用shell来解释执行这个字符串。如果args是个列表,则第一项被视为命令,其余的都视为是给shell本身的参数。也就是说,等效于:
subprocess.Popen(['/bin/sh', '-c', args[0], args[1], ...])

  • stdin stdout和stderr:

stdin stdout和stderr,分别表示子程序的标准输入、标准输出和标准错误。可选的值有PIPE或者一个有效的文件描述符(其实是个正整数)或者一个文件对象,还有None。如果是PIPE,则表示需要创建一个新的管道,如果是None,不会做任何重定向工作,子进程的文件描述符会继承父进程的。另外,stderr的值还可以是STDOUT,表示子进程的标准错误也输出到标准输出。

二、粘包现象

所谓粘包问题主要还是因为接收方不知道消息之间的界限,还有系统缓存区的问题,时间差的原因,不知道一次性提取多少字节的数据所造成的。

须知:只有TCP有粘包现象,UDP永远不会粘包

粘包不一定会发生,如果发生了:1.可能是在客户端已经粘了;2.客户端没有粘,可能是在服务端粘了

缓冲区的作用:存储少量数据

如果你的网络出现短暂的异常或者波动,接收数据就会出现短暂的中断,影响你的下载或者上传的效率。但是,缓

冲区解决了上传下载的传输效率的问题,带来了黏包问题。

收发的本质:不一定是一收一发

三、为什么出现粘包?

1,接收方没有及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)recv会产生黏包(如果recv接受的数据量(1024)小于发送的数据量,第一次只能接收规定的数据量1024,第二次接收剩余的数据量)

2,发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据也很小,会合到一起,产生粘包)send 也可能发生粘包现象。(连续send少量的数据发到输出缓冲区,由于缓冲区的机制,也可能在缓冲区中不断积压,多次写入的数据被一次性发送到网络)

出现粘包现象的代码实例

server. py

import socket
import subprocess

# 建立
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# 绑定
phone.bind(('127.0.0.1', 8081))

# 监听
phone.listen(5)

# 通信循环
while True:
  # 接收客户端连接请求
  conn, client_addr = phone.accept()
  while True:
    # 接收客户端数据/命令
    cmd = conn.recv(1024)
    if not cmd:
      break
    # 创建管道
    obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout = obj.stdout.read()
    stderr = obj.stderr.read()
    # 向客户端发送数据
    conn.send(stdout)
    conn.send(stderr)
  # 结束连接
  conn.close()

# 关闭套接字
phone.close()

client. py

import socket

# 建立
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接
phone.connect(('127.0.0.1', 8081))
while True:
  cmd = input('>>> ').strip()
  if not cmd:
    continue
  if cmd == 'quit':
    break
  # 给服务端发送数据/命令
  phone.send(cmd.encode('utf-8'))
  # 接收服务端数据/命令
  data = phone.recv(1024)
  print(data.decode('utf-8'))

# 关闭套接字
phone.close()

粘包现象运行结果

python基于socket模拟实现ssh远程执行命令

python基于socket模拟实现ssh远程执行命令

python基于socket模拟实现ssh远程执行命令

可以观察到执行两次ls命令后,服务端返回的仍然是ifconfig命令的结果,最后一次ls命令的末尾才出现ls命令返回的部分结果

四、解决粘包问题的代码实例
server. py

import socket
import subprocess
import json
import struct

# 建立
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# 绑定
phone.bind(('127.0.0.1', 8081))

# 监听
phone.listen(5)

# 通信循环
while True:
  # 接收客户端连接请求
  conn, client_addr = phone.accept()
  while True:
    # 接收客户端数据/命令
    cmd = conn.recv(1024)
    if not cmd:
      continue
    # 创建数据流管道
    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',
      'total_size': len(stdout)+len(stderr)
    }
    # 序列化报头
    header_json = json.dumps(header_dic) # 序列化为byte字节流类型
    header_bytes = header_json.encode('utf-8') # 编码为utf-8(Mac系统)
    # 2.先发送报头的长度
    # 2.1 将byte类型的长度打包成4位int
    conn.send(struct.pack('i', len(header_bytes)))
    # 2.2 再发报头
    conn.send(header_bytes)
    # 2.3 再发真实数据
    conn.send(stdout)
    conn.send(stderr)
  # 结束连接
  conn.close()

# 关闭套接字
phone.close()

client. py

import socket
import struct
import json

# 建立
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接
phone.connect(('127.0.0.1', 8081))
while True:
  cmd = input('>>> ').strip()
  if not cmd:
    continue
  if cmd == 'quit':
    break
  # 给服务端发送命令
  phone.send(cmd.encode('utf-8'))
  # 接收服务端数据

  # 1.先收报头长度
  obj = phone.recv(4)
  header_size = struct.unpack('i', obj)[0]
  # 2.收报头
  header_bytes = phone.recv(header_size)
  # 3.从报头中解析出数据的真实信息(报头字典)
  header_json = header_bytes.decode('utf-8')
  header_dic = json.loads(header_json)
  total_size = header_dic['total_size']
  # 4.接受真实数据
  recv_size = 0
  recv_data = b''
  while recv_size < total_size:
    res = phone.recv(1024)
    recv_data += res
    recv_size += len(res)
  print(recv_data.decode('utf-8'))

# 关闭套接字
phone.close()

以上就是python基于socket模拟实现ssh远程执行命令的详细内容,更多关于python基于socket实现ssh远程执行命令的资料请关注三水点靠木其它相关文章!

以上就是python基于socket模拟实现ssh远程执行命令的详细内容,更多关于python socket的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python中使用urllib2防止302跳转的代码例子
Jul 07 Python
python&amp;MongoDB爬取图书馆借阅记录
Feb 05 Python
Tensorflow卷积神经网络实例
May 24 Python
Python安装pycurl失败的解决方法
Oct 15 Python
opencv实现静态手势识别 opencv实现剪刀石头布游戏
Jan 22 Python
Python字典的基本用法实例分析【创建、增加、获取、修改、删除】
Mar 05 Python
Python3实现二叉树的最大深度
Sep 30 Python
python获取全国城市pm2.5、臭氧等空气质量过程解析
Oct 12 Python
浅谈pytorch卷积核大小的设置对全连接神经元的影响
Jan 10 Python
VSCode中autopep8无法运行问题解决方案(提示Error: Command failed,usage)
Mar 02 Python
Python基础之元组与文件知识总结
May 19 Python
python 如何用terminal输入参数
May 25 Python
Python实现PS滤镜中的USM锐化效果
Dec 04 #Python
python 模拟登陆github的示例
Dec 04 #Python
python中round函数保留两位小数的方法
Dec 04 #Python
python中pow函数用法及功能说明
Dec 04 #Python
python对输出的奇数偶数排序实例代码
Dec 04 #Python
python中entry用法讲解
Dec 04 #Python
利用python制作拼图小游戏的全过程
Dec 04 #Python
You might like
教你如何解密 “ PHP 神盾解密工具 ”
2014/06/20 PHP
Laravel 5框架学习之路由、控制器和视图简介
2015/04/07 PHP
smarty简单应用实例
2015/11/03 PHP
PHP与Ajax相结合实现登录验证小Demo
2016/03/16 PHP
Thinkphp单字母函数使用指南
2016/05/08 PHP
ThinkPHP5框架缓存查询操作分析
2018/05/30 PHP
PHP-FPM 的管理和配置详解
2019/02/17 PHP
EASYUI TREEGRID异步加载数据实现方法
2012/08/22 Javascript
javascript实现修改微信分享的标题内容等
2014/12/11 Javascript
Bootstrap入门书籍之(四)菜单、按钮及导航
2016/02/17 Javascript
D3.js实现直方图的方法详解
2016/09/25 Javascript
如何使用JS在HTML中自定义字符串格式化
2017/07/20 Javascript
详解es6超好用的语法糖Decorator
2018/08/01 Javascript
Vue 实现html中根据类型显示内容
2019/10/28 Javascript
jquery实现吸顶导航效果
2020/01/08 jQuery
单线程JavaScript实现异步过程详解
2020/05/19 Javascript
Vue 使用typescript如何优雅的调用swagger API
2020/09/01 Javascript
[01:02:55]CHAOS vs Mineski 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/18 DOTA
Python实现快速排序和插入排序算法及自定义排序的示例
2016/02/16 Python
Python更新数据库脚本两种方法及对比介绍
2017/07/27 Python
python学生信息管理系统(初级版)
2018/10/17 Python
对python 命令的-u参数详解
2018/12/03 Python
python reverse反转部分数组的实例
2018/12/13 Python
python-opencv 将连续图片写成视频格式的方法
2019/01/08 Python
Python生态圈图像格式转换问题(推荐)
2019/12/02 Python
Python操作redis和mongoDB的方法
2019/12/19 Python
美国知名女性服饰品牌:New York & Company
2017/03/23 全球购物
Roxy俄罗斯官方网站:冲浪和滑雪板的一切
2020/06/20 全球购物
教师申诉制度
2014/01/29 职场文书
《特殊的葬礼》教学反思
2014/04/27 职场文书
邻里守望志愿服务活动方案
2014/08/15 职场文书
2014年超市员工工作总结
2014/11/18 职场文书
清明节网上祭英烈寄语2015
2015/03/04 职场文书
清明节主题班会
2015/08/14 职场文书
简单介绍 http请求响应参数、无连接无状态、MIME、状态码、端口、telnet、curl
2021/03/31 HTML / CSS
如何开启Apache,Nginx和IIS服务器的GZIP压缩功能
2022/04/29 Servers