python模拟简单ftp

需求:开发简单的FTP 1. 用户登陆 2. 上传/下载文件 3. 不同用户家目录不同 4. 查看当前目录下文件 5. 充分使用面向对象知识 代码目录结构: 流程图: 客户端代码:

import os,sys
import getpass
import platform
if platform.system() == "Windows":
    BASE_DIR = "\\".join(os.path.abspath(os.path.dirname(__file__)).split("\\")[:-1])
else:
    BASE_DIR = "/".join(os.path.abspath(os.path.dirname(__file__)).split("/")[:-1])
sys.path.insert(0,BASE_DIR)
from modules import ssh

#print(sys.path)

if __name__ == "__main__":
    #host = input("请输入服务器端IP:").strip()
    #port = input("请输入端口:").strip()
    username = input("请输入用户名:").strip()
    password = input("请输入密码:").strip()
    #password = getpass.getpass("请输入密码:").strip()
    ssh.SSH("host","port",username,password)

服务端代码:

import os,sys
import socket
import platform

if platform.system() == "Windows":
    BASE_DIR = "\\".join(os.path.abspath(os.path.dirname(__file__)).split("\\")[:-1])
else:
    BASE_DIR = "/".join(os.path.abspath(os.path.dirname(__file__)).split("/")[:-1])
sys.path.insert(0,BASE_DIR)
from modules import ftp

#从文件获取用户账号信息
def get_acount():
    acount_dict = {}
    f = open(BASE_DIR+"\conf\\acount.conf")
    for account in f:
        acount_dict[account.split()[0]] = account.split()[1]
    return acount_dict

if __name__ == "__main__":
    server = socket.socket()
    server.bind(("localhost",10620))
    server.listen(5)
    print("准备接受连接.....")
    while True:
        conn, addr = server.accept()
        auth = conn.recv(1024)
        username = auth.decode("utf-8").split()[0]
        password = auth.decode("utf-8").split()[1]
        acount = get_acount()
        if username in acount and password == acount[username]:
            conn.send(b"success")
            if os.path.exists(("C:\\Users\%s" %username)):
                home_dir = "C:\\Users\%s" %username
                conn.send(home_dir.encode("utf-8"))
            else:
                os.mkdir("C:\\Users\%s" %username)
                conn.send(home_dir)
            os.chdir(home_dir)
            conn.send("登录成功!命令帮助请输入h或?".encode("utf-8"))
            help = '''
            put [file_name]  上传本地文件到ftp服务器。例如:put file.txt
            get [file_name]  下载ftp服务器文件到本地。例如:get file.txt
            command 执行操作系统命令。例如:dir  ipconfig
            quit|exit|q 退出登录。例如:q
            '''
            while True:
                command = conn.recv(1024).decode("utf-8")
                if command == "?" or command == "h":
                    conn.send(help.encode("utf-8"))
                elif command.split()[0] == "get":# or command.split()[0] == "put":  #判断用户是否执行ftp命令
                        if len(command.split()) != 2:
                            conn.send(("%s命令格式为:%s FileName" %(command.split()[0],command.split()[0])).encode("utf-8"))
                            continue
                        else:
                            Ftp = ftp.FTP(conn,command.split()[0],command.split()[1])  #调用FTP模块传输文件
                            Ftp.download()
                elif command.split()[0] == "put":  # 判断用户是否执行ftp命令
                    f = open(command.split()[1], "wb")
                    fsize = conn.recv(1024).decode("utf-8")
                    conn.send(b"ok")
                    while True:
                        data = conn.recv(102400)
                        f.write(data)
                        f.flush()
                        if os.path.getsize(command.split()[1]) == int(fsize):
                            break
                    f.close()
                elif command == "q" or command == "quit" or command == "exit":
                    conn.send("q".encode("utf-8"))
                    conn.close()
                    break
                else:
                    res = os.popen(command).read()
                    if len(res) == 0:  #如果是不存在的系统命令,则提醒用户输入错误
                        conn.send(("%s:command not found" % command).encode("utf-8"))
                    else: #以上条件都不符合后执行此步骤,此块内容为执行系统命令
                        conn.sendall(res.encode("utf-8"))
            continue
        else:
            print(2222)
            conn.close()
            continue
    server.close()

ssh模块:

import os,sys
import socket
import platform
if platform.system() == "Windows":
    BASE_DIR = "\\".join(os.path.abspath(os.path.dirname(__file__)).split("\\")[:-1])
else:
    BASE_DIR = "/".join(os.path.abspath(os.path.dirname(__file__)).split("/")[:-1])
sys.path.insert(0,BASE_DIR)
from modules import ftp

class SSH(object):
    def __init__(self,host,port,username,password):
        client = socket.socket()
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        #client.connect((self.host,int(self.port)))
        client.connect(("localhost",10620))
        #登录时将账号发送到服务端进行验证,验证通过后进入循环命令输入
        #client.send((self.username+" "+self.password).encode("utf-8"))
        client.send(("zhaohh" + " " + "123").encode("utf-8"))
        auth_res = client.recv(1024)
        if auth_res.decode("utf-8") == "success":
            home_dir = client.recv(1024)  #获取用户登录成功后的家目录
            welcom = client.recv(1024)
            print(welcom.decode("utf-8"))
            while True:
                command = input("[%s]$ "%home_dir.decode("utf-8")).strip()
                if len(command) == 0:continue
                client.send(command.encode("utf-8"))
                if command.split()[0] == "get":
                    f = open(command.split()[1],"wb")
                    fsize = client.recv(1024).decode("utf-8")
                    client.send(b"ok")
                    while True:
                        data = client.recv(102400)
                        f.write(data)
                        f.flush()
                        if os.path.getsize(command.split()[1]) == int(fsize):
                            break
                    f.close()
                elif command.split()[0] == "put":
                    if len(command.split()) != 2:
                        print("%s命令格式为:%s FileName" % (command.split()[0], command.split()[0]))
                        continue
                    else:
                        Ftp = ftp.FTP(client, command.split()[0], command.split()[1])  # 调用FTP模块传输文件
                        Ftp.upload()
                else:
                    res = client.recv(102400)
                    if res.decode("utf-8") == "q":
                        exit("已退出登录!")
                    else:
                        print(res.decode())
        else:
            input("账号错误!")

ftp模块:

import os
class FTP(object):
    def __init__(self,conn,command,filename):
        self.command = command
        self.filename = filename
        self.conn = conn

    #上传文件
    def upload(self):
        print("上传文件:%s" %self.filename)
        f = open(self.filename,"rb")
        data = f.read()
        fsize = os.path.getsize(self.filename)
        self.conn.send(str(fsize).encode("utf-8"))
        self.conn.recv(1024)
        self.conn.sendall(data)

    #下载文件
    def download(self):
        f = open(self.filename,"rb")
        data = f.read()
        fsize = os.path.getsize(self.filename)
        self.conn.send(str(fsize).encode("utf-8"))
        self.conn.recv(1024)
        self.conn.sendall(data)

用户账号文件内容格式: zhaohh 123 alex 123

相关文章
相关标签/搜索