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实现随机密码字典生成器示例
Apr 09 Python
python 定义给定初值或长度的list方法
Jun 23 Python
Scrapy-Redis结合POST请求获取数据的方法示例
May 07 Python
Python实现带下标索引的遍历操作示例
May 30 Python
pyqt5实现绘制ui,列表窗口,滚动窗口显示图片的方法
Jun 20 Python
对Python 中矩阵或者数组相减的法则详解
Aug 26 Python
python中字典按键或键值排序的实现代码
Aug 27 Python
将tensorflow.Variable中的某些元素取出组成一个新的矩阵示例
Jan 04 Python
python requests.get带header
May 05 Python
django 模版关闭转义方式
May 14 Python
解决pytorch多GPU训练保存的模型,在单GPU环境下加载出错问题
Jun 23 Python
Ubuntu配置Pytorch on Graph (PoG)环境过程图解
Nov 19 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代码
2010/08/08 PHP
使用PHP遍历文件夹与子目录的函数代码
2011/09/26 PHP
laravel 4安装及入门图文教程
2014/10/29 PHP
php简单日历函数
2015/10/28 PHP
thinkPHP使用pclzip打包备份mysql数据库的方法
2016/04/30 PHP
PHP7匿名类用法分析
2016/09/26 PHP
php array_udiff_assoc 计算两个数组的差集实例
2016/11/12 PHP
Javascript解决常见浏览器兼容问题的12种方法
2010/01/04 Javascript
Json对象替换字符串占位符实现代码
2010/11/17 Javascript
JS获得选取checkbox整行数据的方法
2015/01/28 Javascript
浅谈Jquery核心函数
2015/06/18 Javascript
JS判断页面是否出现滚动条的方法
2015/07/17 Javascript
Bootstrap风格的WPF样式
2016/12/07 Javascript
jQuery实现花式轮播之圣诞节礼物传送效果
2016/12/25 Javascript
微信小程序中button去除默认的边框实例代码
2019/08/01 Javascript
vue学习笔记之slot插槽用法实例分析
2020/02/29 Javascript
[01:18:31]DOTA2-DPC中国联赛定级赛 LBZS vs Magma BO3第一场 1月10日
2021/03/11 DOTA
Python ftp上传文件
2016/02/13 Python
Django卸载之后重新安装的方法
2017/03/15 Python
Python实现两个list对应元素相减操作示例
2017/06/09 Python
Python实现将json文件中向量写入Excel的方法
2018/03/26 Python
matlab中实现矩阵删除一行或一列的方法
2018/04/04 Python
Python定义二叉树及4种遍历方法实例详解
2018/07/05 Python
python 批量修改/替换数据的实例
2018/07/25 Python
python GUI框架pyqt5 对图片进行流式布局的方法(瀑布流flowlayout)
2020/03/12 Python
有趣的Python图片制作之如何用QQ好友头像拼接出里昂
2020/04/22 Python
使用Python3 poplib模块删除服务器多天前的邮件实现代码
2020/04/24 Python
CSS3使用border-radius属性制作圆角
2014/12/22 HTML / CSS
关于老式浏览器兼容HTML5和CSS3的问题
2016/06/01 HTML / CSS
美国购买隐形眼镜网站:Lenses For Less
2020/07/05 全球购物
西安兵马俑导游词
2015/02/02 职场文书
天鹅湖观后感
2015/06/09 职场文书
爱心捐赠活动简讯
2015/07/20 职场文书
三八妇女节致辞
2015/07/31 职场文书
Android自定义双向滑动控件
2022/04/19 Java/Android
利用nginx搭建RTMP视频点播、直播、HLS服务器
2022/05/25 Servers