第八章 socket网络编程:模拟ssh远程执行命令
Posted py小强
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第八章 socket网络编程:模拟ssh远程执行命令相关的知识,希望对你有一定的参考价值。
接下来我们用之前的知识,模拟一个远程执行命令的小程序
server.py
import socket
import subprocess
import locale
ssh_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 初始化一个socket连接对象
ssh_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
ssh_server.bind(('127.0.0.1', 8080)) # 注意bind只需要一个参数,元组类型
ssh_server.listen(3)
while True:
conn, addr = ssh_server.accept()
while True: # 从这里开始,我们使用的对象就是连接对象conn了
try:
# 接收命令字符串
cmd = conn.recv(1024).decode('utf-8') # 传来的是bytes类型,需要decode
if not cmd: break
print("excute cmd:", cmd)
# 执行命令,拿到结果
# import os
# res = os.system(cmd) # 使用os模块来执行cmd,但是os.system()没有返回值※return 0,这样我们没法返回结果给客户端
obj = subprocess.Popen(cmd, shell=True, # 使用subprocess模块可以实现要求
stdout=subprocess.PIPE, # 生成一个管道,用来输出执行的结果
stderr=subprocess.PIPE) # 生成一个管道,用来接收error信息
stdout = obj.stdout.read() # 从管道读取执行结果,结果是bytes类型,
stderr = obj.stderr.read() # 读取error结果
# 注意,read()只能读取一次,第二次会取不到内容
# stdout1 = obj.stdout.read() # 这个是空的
# print(stdout1) # 打印一下看看,结果是 b''
# 注意,操作系统会用默认的编码来encode(linux:utf-8,windows:因os语言而异),所以print的时候需要注意
os_locale = locale.getdefaultlocale() # 我们使用locale模块来获取默认的区域设置并返回元祖(语言, 编码)
os_encode = os_locale[1]
# print(locale.getdefaultlocale()) # ('ja_JP', 'cp932')
print(stdout.decode(os_encode))
# 把命令结果返回给客户端
conn.send(stdout+stderr) # 这个+是个可以优化的点
except ConnectionResetError as e:
print(e)
break
conn.close()
ssh_server.close()
client.py
import socket
ssh_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssh_client.connect(('127.0.0.1', 8080))
while True:
# 发命令
cmd = input(">>>>:").strip()
if not cmd:continue
ssh_client.send(cmd.encode('utf-8'))
# 取得返回的结果并打印
data = ssh_client.recv(1024) # 1024是一个坑:超过1024字节,解码的时候就会混乱
print(data) # 服务器的执行结果是服务器OS用其默认编码来encode的(linux:utf-8,windows:因os语言而异),客户端decode时需注意
# 可能是因为传来的bytes类型不完整,导致没法正确解码,Windows系统下报错了,Linux系统似乎不会报错,但是会粘包
try: # 这个异常处理是为了防止,客户端解码失败报错导致强制结束socket连接
print(data.decode('cp932')) # 这里知道服务器os的编码是cp932,所以固定写成这个了。如果encode指定错误会报错
except Exception as e:
print(e)
ssh_client.close()
以上是关于第八章 socket网络编程:模拟ssh远程执行命令的主要内容,如果未能解决你的问题,请参考以下文章
第六章 - 网络编程 - 1.简单的套接字通信/2.加上通信循环/3.bug修复/4.加上链接循环/5.模拟ssh远程执行命令