基于TCP协议模拟ssh远程执行命令的CS架构软件

基于TCP协议模拟ssh远程执行命令的CS架构软件

一、引入

在socket的模块可以发送数据消息的基础上,我们想远程发送一些系统命令来远程调试服务器。执行系统命令的模块一开始可能给会想到os模块,如下:

import os
res= os.system("dir")
print("命令的结果:",res)
'''
Windows操作系统的的常用命令:
dir\ :查看某一个文件夹下的子文件名与子文件夹名
ipconfig: 查看本地网卡的ip地址
tasklist :查看运行的进程
'''

输出结果如下:

基于TCP协议模拟ssh远程执行命令的CS架构软件_第1张图片

这里显示乱码,因为windows系统上文件都为gbk,但是pycharm上的Global Encodingutf-8,所以乱码。

我们在这里看到把res取出来结果为0,这个0是来判断命令是否执行。0代表执行,非0的数字代表执行错误。

提示:

开发一个远程执行命令的软件,服务端必须满足至少三点:

  1. 绑定一个固定的ip和port
  2. 一直对外提供服务,稳定运行
  3. 能够支持并发

所以,OS模块根本拿不到我们想要的结果。

二、模拟xshell远程执行命令的实现

1、引入subprocess模块

在这里,我们引入可以用subprocess模块来实现。

subprocess模块定义了一个类: Popen

1.1类原型:

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)

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

  • argsargs参数。可以是一个字符串,可以是一个包含程序参数的列表。要执行的程序一般就是这个列表的第一项,或者是字符串本身。
  • 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,表示子进程的标准错误也输出到标准输出。

2、ssh远程执行命令的实现

介绍完以上,我们就开始基于socket和subprocess动手写代码了。

2.1、TCP服务端

from socket import *
import subprocess   # 允许我们启动一个新进程,并连接到它们的输入/输出/管道,从而获取返回值

server = socket(AF_INET,SOCK_STREAM)
server.bind(("127.0.0.1",9903))
server.listen(5)

while True:  #连接循环
    print("Waiting for connection...")
    conn,addr = server.accept()
    print(f"来自{addr}的连接")
    while True: #循环通讯
        try:
            cmd = conn.recv(1024)
            # 运行系统命令
            if not  cmd:
                '''
                这里解决的问题是:
                1.当你的程序在linux系统中,客户端强制断开连接,服务端会会收到空数据,在这种情况下就会退出与当前客户端的通讯循环,
                    并关闭与该客户端的连接, 并回收当前客户端在服务端当前所占的系统资源。
                2.还有另一种情况就是客户端正常使用close()断开连接, 服务端也会收到空的数据。
                '''
                break

            # 创建管道,执行命令、拿到结果
            obj=subprocess.Popen(
                cmd.decode("utf-8"),    #输入cmd命令
                shell=True, #通过shell运行
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,

            )
            res1=obj.stdout.read()    #从正确输出管道中读数据
            res2 = obj.stderr.read()  # 从错误输出管道中读数据

            conn.send(res1+res2)    #返回命令执行的结果
        except Exception:
            '''
            这里解决的问题是:
            1.当你的程序运行在windows系统中,客户端强制断开链接,服务端就会引发异常. 因此,就可以使用异常处理机制来监测这种异常,
                此时一旦监测出这种异常,就代表客户端强制断开了链接.
            2.在这种情况下就会退出与当前客户端的通讯循环,并关闭与该客户端的连接, 并回收当前客户端在服务端当前所占的系统资源,
            '''
            break
    conn.close()
server.close()

2.2、TCP客户端

from socket import *

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

while True:
    cmd = input('请输入命令>>').strip()
    if not cmd:
        '''
        # 这里解决的问题,当客户端输入为空的时候,在客户端的操作系统缓存中,并没有数据能发送给服务端. 硬件不能识别你这个空的数据,只有我们这种逻辑层面才有这种空的数据的存在.
        # 因此服务端的recv操作会在服务端的操作缓存中拿取数据,但是与此同时,服务端的操作系统缓存中并没有数据,于是服务端一直在recv堵塞状态.
        # 接着客户端因为send发送了数据,处于recv等待服务端发送回来的数据的状态,因而两者会处于一种recv堵塞的状态,
        '''
        continue

    client.send(cmd.encode("utf-8"))
    res=client.recv(1024)   #发送内容大于1024会出现粘包
    print(res.decode('gbk'))   #注意如果是linux系统,字符编码应该改为utf-8,否则报错:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb2 in position 5: invalid start byte

输出结果如下:

基于TCP协议模拟ssh远程执行命令的CS架构软件_第2张图片

3、问题:数据接受不完整

输入dir命令,由于服务端发送字节少于1024字节,客户端可以接受。

输入tasklist命令,由于服务端发送字节多于1024字节,客户端只接受部分数据,并且当你再次输入dir命令的时候,客户端会接收dir命令的结果,但是会打印上一次的剩余未发送完的数据,会出现粘包问题

基于TCP协议模拟ssh远程执行命令的CS架构软件_第3张图片

针对以上问题:,我们可以在客户端调高最大接收量, 但这并不是我们的解决方案, 于是我们就可以对接收的字节进行循环接收, 直到接收完为止,如下:

TCP客户端循环接收数据
from socket import *

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

while True:
    cmd = input('请输入命令>>').strip()
    if not cmd:
        '''
        # 这里解决的问题,当客户端输入为空的时候,在客户端的操作系统缓存中,并没有数据能发送给服务端. 硬件不能识别你这个空的数据,只有我们这种逻辑层面才有这种空的数据的存在.
        # 因此服务端的recv操作会在服务端的操作缓存中拿取数据,但是与此同时,服务端的操作系统缓存中并没有数据,于是服务端一直在recv堵塞状态.
        # 接着客户端因为send发送了数据,处于recv等待服务端发送回来的数据的状态,因而两者会处于一种recv堵塞的状态,
        '''
        continue

    client.send(cmd.encode("utf-8"))
    while True:
        res=client.recv(1024)   #发送内容大于1024会出现粘包
        print(res.decode('gbk'))   #注意如果是linux系统,字符编码应该改为utf-8
        if len(res)< 1024 :break

输出结果如下:

基于TCP协议模拟ssh远程执行命令的CS架构软件_第4张图片

最后附赠宝典,cmd命令锦集,如下

四、附赠宝典:

CMD命令锦集

CMD命令锦集
      1. gpedit.msc-----组策略
  2. sndrec32-------录音机
  3. Nslookup-------IP地址侦测器 ,是一个 监测网络中 DNS 服务器是否能正确实现域名解析的命令行工具。 它在 Windows NT/2000/XP 中均可使用 , 但在 Windows 98 中却没有集成这一个工具。
  4. explorer-------打开资源管理器
  5. logoff---------注销命令
  6. shutdown-------60秒倒计时关机命令
  7. lusrmgr.msc----本机用户和组
  8. services.msc---本地服务设置
  9. oobe/msoobe /a----检查XP是否激活
  10. notepad--------打开记事本
  11. cleanmgr-------垃圾整理
  12. net start messenger----开始信使服务
  13. compmgmt.msc---计算机管理
  14. net stop messenger-----停止信使服务
  15. conf-----------启动netmeeting
  16. dvdplay--------DVD播放器
  17. charmap--------启动字符映射表
  18. diskmgmt.msc---磁盘管理实用程序
  19. calc-----------启动计算器
  20. dfrg.msc-------磁盘碎片整理程序
  21. chkdsk.exe-----Chkdsk磁盘检查
  22. devmgmt.msc--- 设备管理器
  23. regsvr32 /u *.dll----停止dll文件运行
  24. drwtsn32------ 系统医生
  25. rononce -p----15秒关机
  26. dxdiag---------检查DirectX信息
  27. regedt32-------注册表编辑器
  28. Msconfig.exe---系统配置实用程序
  29. rsop.msc-------组策略结果集
  30. mem.exe--------显示内存使用情况
  31. regedit.exe----注册表
  32. winchat--------XP自带局域网聊天
  33. progman--------程序管理器
  34. winmsd---------系统信息
  35. perfmon.msc----计算机性能监测程序
  36. winver---------检查Windows版本
  37. sfc /scannow-----扫描错误并复原
  38. taskmgr-----任务管理器(2000/xp/2003
  40. wmimgmt.msc----打开windows管理体系结构(WMI)
  41. wupdmgr--------windows更新程序
  42. wscript--------windows脚本宿主设置
  43. write----------写字板
  45. wiaacmgr-------扫描仪和照相机向导
  46. winchat--------XP自带局域网聊天
  49. mplayer2-------简易widnows media player
  50. mspaint--------画图板
  51. mstsc----------远程桌面连接
  53. magnify--------放大镜实用程序
  54. mmc------------打开控制台
  55. mobsync--------同步命令
  57. iexpress-------木马捆绑工具,系统自带
  58. fsmgmt.msc-----共享文件夹管理器
  59. utilman--------辅助工具管理器
  61. dcomcnfg-------打开系统组件服务
  62. ddeshare-------打开DDE共享设置
  110. osk------------打开屏幕键盘
  111. odbcad32-------ODBC数据源管理器
  112. oobe/msoobe /a----检查XP是否激活
  68. ntbackup-------系统备份和还原
  69. narrator-------屏幕“讲述人”
  70. ntmsmgr.msc----移动存储管理器
  71. ntmsoprq.msc---移动存储管理员操作请求
  72. netstat -an----(TC)命令检查接口
  73. syncapp--------创建一个公文包

至于粘包问题,后续更新…

你可能感兴趣的:(Python学习笔记,python,socket,shell,linux,java)