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()