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

  

 

posted @ 2018-04-10 21:21  whz_it  阅读(215)  评论(0编辑  收藏  举报