模拟一个SSH“远程”执行命令并获取命令结果的一个程序:

  1、在C/S架构下,当客户端与服务器建立连接(这里以TCP为例)后,二者可以不断的进行数据交互。SSH远程可以实现的效果是客户端输入命令可以在服务器中执行并且可以将结果返回给客户端。但是需要注意的一点事:客户端的“命令”在计算机看来仅仅是“字符串”而已,而真正需要执行的“命令”必须是操作系统能够识别的!也就是说,真正“执行命令”与“返回结果”的地方仍然是服务器端。在客户端我们只是“显示”出了一个这样的知执行假象而已。

  那么,这样的一个SSH远程执行程序的具体流程是怎样的呢?

  下图是这样的一个简单过程:

  简单的过程说明:

  对于客户端来讲,用户首先输入了str类型的命令command,然后程序将这个str类型的字符串encode成能够在网络中传输的bytes类型的数据并发送给服务器;服务器接收到以后将其重新解码为str,然后在本段“执行”这段代码生成str类型的结果,接着再进行编码传给客户端,客户端接收到以后解码为人能识别的str类型最终输出到屏幕上。

  2、这个过程有两个大问题:一个是服务器端是如何进行“代码执行”的,另一个就是客户端与服务器端str与bytes格式数据的编解码问题。

  2.1、对于第一个问题,我们利用subprocess模块下的Popen方法可以将str类型的“虚假命令”转换为操作系统能够识别的“真是命令”:

import subprocess

cmd = input('>>>:')
obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) print(obj.stdout.read().decode('gbk'))
print(obj.stderr.read().decode('gbk'))

  这里有几点需要说明:

  (1)可以把obj看成是一个管道,它一次性的、毫无保留将所有执行结果都拿到,再一次取值时里面没有了数据,这就像一个“管道”一样,里面的数据全部取完后就“无所保留”了。

  (2)关于输出结果解码的问题:subprocess模块下的Popen方法在不同的操作系统下结果的编码方式不同:linux下为utf-8模式,windows下为gbk模式。由于本例是在windows操作系统下进行的,所以我们在输出是要进行gbk的方式解码才能看到结果。

  (3)最终的结果包含正确的信息stdout与错误的结果stderr(当用户输入一个不存在的命令时产生)。

  2.2、第二个编解码问题可以看下图具体的描述:

  

  这里需要注意的一点是:本例是在windows操作系统下执行的,所以result的编码方式要以gbk模式进行,这样才不会在客户端中产生乱码。

  程序的代码以及运行结果为:

import socket
import subprocess server_whw = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_whw.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
server_whw.bind(('127.0.0.1',8008))
server_whw.listen(5)
print('Starting......')
conn,client_addr = server_whw.accept() while 1:
try:
cmd = conn.recv(8096)
#将从客户端传来的命令信息进行处理
obj = subprocess.Popen(cmd.decode('utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
#将结果返回给客户端
stdout = obj.stdout.read().decode('gbk')
stderr = obj.stderr.read().decode('gbk') std1 = stdout.encode('gbk')
std2 = stderr.encode('gbk')
conn.send(std1)
conn.send(std2) except ConnectionResetError:
print('连接断开')
break
conn.close()
server_whw.close()

Server_ssh

import socket

client_whw = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client_whw.connect(('127.0.0.1',8008))
while 1:
cmd = input('请输入命令:')
if not cmd:
continue
client_whw.send(cmd.encode('utf-8'))
data = client_whw.recv(1024)
print('命令结果:\n',data.decode('gbk'))
# client_whw.close()

Client_ssh

  程序演示:

当然,最终的结果出现了粘包问题~需要进行进一步的处理

最新文章

  1. Ambari服务依赖关系图生成脚本
  2. 带搜索的ComboBox
  3. 使用NuGet发布自己的类库包(Library Package)
  4. sublime text 3 3114 注册码
  5. CentOS7:安装Zabbix
  6. [Leetcode] Recover Binary Search Tree
  7. 利用JS提交表单的几种方法和验证
  8. 卡特兰数 BZOJ3907 网格 NOIP2003 栈
  9. Tomcat中JSP引擎工作原理
  10. 生成shadow中hash字串
  11. 不是技术牛人,如何拿到国内IT巨头的Offer
  12. Objective-C马路成魔【14-关键C语言功能】
  13. 结构-行为-样式-AngularJs--指令实现 手动触发响应到页面指定位置
  14. spring两大核心对象IOC和AOP(新手理解)
  15. 使用Supervisor守护Python进程
  16. Flex实现双轴条状图
  17. MyBatis与MySQL交互
  18. node api 之:Error
  19. oozie-ext
  20. 常用Javascript函数与原型功能收藏

热门文章

  1. springMvc前后台传值各种情况
  2. Java基础五(方法)
  3. zabbix使用自定义key进行监控
  4. auto_ptr & share_ptr & unique_ptr
  5. Javascript高级调试——console.table()
  6. day 29 socketsetserver 模块
  7. SelectDataTable
  8. 我发起了一个 支持 PostgreSql 的 外围设施 的 .Net 开源项目
  9. COM,SOM, QT, GObject, ObjectiveC
  10. Linux下Redis开机自启(Centos6)