ssh+ftp+1
使用subprocess和ThreadingTCPServer实现并发的ssh与ftp服务器,可以实现常用的cd,ls,mkdir,touch等包括其带参数的命令,more命令在小文件上行,也就是不是一次性获取结果命令还不能实现,等再研究研究,能实现文件上传下载,有一定的容错能力。
server端
import json
import socketserver
import subprocess
import os
from itertools import chain
class MyServer(socketserver.BaseRequestHandler):
def common_command(self,clean_data):
print(clean_data["command"])
if clean_data["command"] == "pwd":
res = clean_data["cur_dir"]
len_data = len(clean_data["cur_dir"])
else:
split_command = clean_data["command"].split()
command = ""
if len(split_command) == 1:
command = split_command[0] + " " + clean_data["cur_dir"]
else:
command += split_command[0] + " "
for i in range(1,len(split_command)):
if split_command[i].startswith("-") or split_command[i].startswith("|"):
command += split_command[i] + " "
if split_command[-1].startswith("/"):
command += split_command[-1]
elif not split_command[-1].startswith("/") and not split_command[-1].startswith("-"):
command += clean_data["cur_dir"] + "/" + split_command[-1]
elif split_command[-1].startswith("-"):
command += clean_data["cur_dir"]
print(command)
res = subprocess.getoutput(command)
len_data = len(res)
if not res:
res = '%s successful'%command
len_data = len(res)
self.request.sendall(("%s"%len_data).encode("utf-8"))
self.request.sendall(res.encode("utf-8"))
def chdir(self,clean_data):
command = clean_data["command"]
cur_dir = clean_data["cur_dir"]
send_all_msg = {
"reason": None,
"cur_dir":cur_dir
}
if command == "cd":
send_all_msg["cur_dir"] = "/root"
elif len(command.split()) < 2:
send_all_msg["reason"] = "请输入正确的格式"
elif command.split()[1]== ".":
send_all_msg["cur_dir"] = cur_dir
elif command.split()[1] == "..":
if cur_dir == "/":
send_all_msg["cur_dir"] = cur_dir
else:
if len(cur_dir.split("/")) == 2:
send_all_msg["cur_dir"] = "/"
else:
send_all_msg["cur_dir"] = "/".join(cur_dir.split("/")[:-1])
print("else",cur_dir)
elif command.split()[1].startswith("/"):
send_all_msg["cur_dir"] = command.split()[1]
else:
send_all_msg["cur_dir"] = cur_dir + "/"+ command.split()[-1]
if os.path.isdir(send_all_msg["cur_dir"]):
send_all_msg = json.dumps(send_all_msg)
self.request.sendall(send_all_msg.encode("utf-8"))
else:
send_all_msg["reason"] = "目录不存在或不是目录"
send_all_msg["cur_dir"] = clean_data["cur_dir"]
send_all_msg = json.dumps(send_all_msg)
self.request.sendall(send_all_msg.encode("utf-8"))
def rz(self,clean_data):
command = clean_data["command"].split(" ")
cur_dir = clean_data["cur_dir"]
status = {
"code":"0",
"detail":"",
"data_len":"0",
"file_name":"",
}
if len(command) == 2 and command[0] == "rz":
if command[1].startswith("/"):
file_name = command[1]
else:
if cur_dir == "/":
file_name = "/"+command[1]
else:
file_name = cur_dir+"/"+command[1]
print(file_name)
status["file_name"] = file_name
if os.path.isfile(file_name):
len_file = os.path.getsize(file_name)
status["detail"] = "正在下载"
status["data_len"] = str(len_file)
status = json.dumps(status)
self.server.sendall(status.encode("utf-8"))
with open(file_name,'rb') as f:
for line in f:
self.server.sendall(line)
else:
status["code"] = "-1"
status["detail"] = "%s不存在" % file_name
status = json.dumps(status)
self.server.sendall(status.encode("utf-8"))
else:
status["code"] = "-1"
status["detail"] = "格式为'rz filename'"
status = json.dumps(status)
self.server.sendall(status.encode("utf-8"))
print(status)
def save(self,clean_data):
file_name = clean_data["file_name"]
cur_dir = clean_data["cur_dir"]
recived_data = b""
recived_size = 0
file_len = int(clean_data["file_len"])
with open(cur_dir + "/" + file_name, "wb") as f:
while recived_size < file_len:
data = self.server.recv(1024)
recived_size += len(data)
recived_data += data
f.write(data)
def sz(self,clean_data):
file_name = clean_data["file_name"]
cur_dir = clean_data["cur_dir"]
if os.path.isfile(cur_dir+"/"+file_name):
status = b"-1"
self.server.sendall(status)
if_sz = self.server.recv(1024)
print(if_sz)
if if_sz == b"0":
self.save(clean_data)
self.server.sendall("上传完成".encode("utf-8"))
else:
pass
else:
status = b"0"
self.server.sendall(status)
self.save(clean_data)
self.server.sendall("上传完成".encode("utf-8"))
def handle(self):
self.server = self.request
cur_dir = "%s"%subprocess.getoutput("pwd")
self.server.sendall("这是我的socketserver,欢迎使用".encode("utf-8"))
self.server.sendall(cur_dir.encode("utf-8"))
while True:
try:
data = self.server.recv(1024).decode("utf-8")
if data == "exit":
print("%s已断开"%self.client_address[0])
self.request.sendall("谢谢使用!".encode("utf-8"))
break
clean_data = json.loads(data)
if hasattr(self,clean_data["command_type"]):
getattr(self,clean_data["command_type"])(clean_data)
except Exception:
print("%s已断开" % self.client_address[0])
break
if __name__ == "__main__":
server = socketserver.ThreadingTCPServer(('0.0.0.0',9002),MyServer)
server.allow_reuse_address = True
print("启动服务器")
server.serve_forever()
client端
import socket
import json
import os
class Client():
def __init__(self,ip,port):
self.client = socket.socket()
self.ip = ip
self.port = port
def to_json(self,msg,command_type):
all_msg = {
"command_type": command_type,
"command": msg,
"cur_dir": self.cur_dir
}
all_msg = json.dumps(all_msg)
return all_msg
def common_command(self,msg):
all_msg = self.to_json(msg,"common_command")
self.client.sendall(all_msg.encode("utf-8"))
len_data = self.client.recv(1024).decode("utf-8")
recived_data = ""
recived_size = 0
while recived_size < int(len_data):
data = self.client.recv(1024).decode("utf-8")
recived_size += len(data)
recived_data += data
print(recived_data)
def chdir(self,msg):
all_msg = self.to_json(msg,"chdir")
self.client.sendall(all_msg.encode("utf-8"))
recv_data = self.client.recv(1024).decode("utf-8")
recv_data = json.loads(recv_data)
reason = recv_data["reason"]
self.cur_dir = recv_data["cur_dir"]
if reason != None:
print(reason)
def rz(self,msg):
all_msg = self.to_json(msg,"rz")
self.client.sendall(all_msg.encode("utf-8"))
recv_data = self.client.recv(1024).decode("utf-8")
recv_data = json.loads(recv_data)
status_code = recv_data["code"]
if status_code == "0":
len_data = recv_data["data_len"]
print(recv_data["detail"])
recived_data = b""
recived_size = 0
with open(recv_data["file_name"].split("/")[-1],"wb") as f:
while recived_size < int(len_data):
data = self.client.recv(1024)
recived_size += len(data)
recived_data += data
f.write(data)
print("下载完成")
print(len_data,recived_size)
else:
print(recv_data["detail"])
def upload(self,file_name):
with open(file_name, 'rb') as f:
for line in f:
self.client.sendall(line)
res = self.client.recv(1024).decode("utf-8")
print(res)
def sz(self,msg):
msg = msg.split(" ")
if len(msg) == 2 and msg[0] == "sz":
if os.path.isfile(msg[1]):
file_len = os.path.getsize(msg[1])
if "/" in msg[1]:
file_name = msg.split("/")[-1]
elif "\\" in msg[1]:
file_name = msg.split("\\")[-1]
else:
file_name = msg[1]
all_msg = {
"command_type": "sz",
"file_len":str(file_len),
"cur_dir": self.cur_dir,
"file_name":file_name
}
all_msg = json.dumps(all_msg)
self.client.sendall(all_msg.encode("utf-8"))
status = self.client.recv(1024)
if status == b"-1":
if_sz = input("文件已存在,是否继续上传,上传将覆盖 y/n?")
if if_sz == "y":
self.client.sendall(b"0")
print("正在上传")
self.upload(file_name)
else:
self.client.sendall(b"-1")
print("取消上传")
else:
print("正在上传")
self.upload(file_name)
else:
print("%s不存在"%msg[1])
else:
print("格式为sz filename")
def run_client(self):
self.client.connect((self.ip,self.port))
self.client.settimeout(5)
data = self.client.recv(1024).decode("utf-8")
self.cur_dir = self.client.recv(1024).decode("utf-8")
print("server",data)
while True:
msg = input("[root@localhost %s]"%self.cur_dir)
if not msg:
continue
if msg == "exit":
self.client.sendall(msg.encode("utf-8"))
data = self.client.recv(1024).decode("utf-8")
print(data)
break
if msg.startswith("cd"):
self.chdir(msg)
elif msg.startswith("rz"):
self.rz(msg)
elif msg.startswith("sz"):
self.sz(msg)
else:
self.common_command(msg)
self.client.close()
if __name__ == "__main__":
platform = "windows"
client = Client('192.168.171.129',9002)
client.run_client()
浙公网安备 33010602011771号