嘘~ 正在从服务器偷取页面 . . .

网络通信编程学习(9)/ FTP项目(3) ——目录切换、目录查看功能


调用功能函数以及对参数数量进行判断

客户端 server 文件夹下 FTPClient.py

    def interactive(self):
        """交互指令,调用功能函数"""
        if self.auth(): # 登陆成功
            while True:
                command = input(self.show_to_client).strip()
                if not command:continue
                command = command.split()
                action_type = command[0] # 用户输入的命令类似于终端命令
                if hasattr(self, action_type): # 如果 客户端的类中有 action_type 的函数方法
                    func = getattr(self, action_type) # 执行
                    func(command[1: ]) # 执行的函数传入的参数应为 action_type 之后的部分
                else:
                    print("Error: this command does not exist !")

    def parameter_length_judgment(self, command,min_size=None, most_size=None, exact_size=None):
        """判断命令中参数个数是否符合规范,比如说 下载功能 至少要提供文件名的参数"""
        if min_size: # 至少提供的参数个数
            if len(command) < min_size:
                print("Error: supply parameter at least %s, but supply %s parameter" % (min_size, len(command)))
                return False
        if most_size: # 可以提供的最多参数数量
            if len(command) > most_size:
                print("Error: supply parameter at most %s, but supply %s parameter" % (most_size, len(command)))
                return False
        if exact_size: # 应该提供的精确的参数数量
            if len(command) != exact_size:
                print("Error: should supply %s parameter, but supply %s parameter" % (exact_size, len(command)))
                return False

        return True

状态码的变化

服务端 lib 文件夹下 main.py

# 状态码
    STATUS_CODE = {
        200: "User login succeeded !", # 用户登陆成功
        201: "Error: wrong username or wrong password !", # 错误用户名或密码
        202: "Action_type does not exist !", # 没有该函数可以执行
        300: "Check Dir !",
        301: "Dir does not exist !"
    }

查看服务端当前目录

客户端 server 文件夹下 FTPClient.py

    def ls(self, command):
        """查看服务端当前目录"""
        # 因为该函数是查看服务端当前目录,所以不用管会传入多少参数,即最少传入 0 给参数
        if self.parameter_length_judgment(command=command, min_size=0): # if True
            self.create_header_send(action_type="ls")

            response = self.get_response()
            # print(response)

            # 消息的总大小
            total_size = response.get("size")

            # 为断点续存做准备
            self.current_dir = response.get("current_dir")

            recv_size = 0
            res = b""
            # 循环接收信息
            while recv_size < total_size:
                data = self.client.recv(self.MSG_SIZE)
                res += data
                recv_size += len(data)
            else:
                print(res.decode("gbk"))

服务端 lib 文件夹下 main.py

用户登录成功时,增加的代码

            if str(md5_password) == str(ini_password): # 如果密码正确
                self.send_response(status_code=200)
                self.current_dir = os.path.join(self.user_home, username) # 增加的代码部分
                # print(self.current_dir)

实现功能的代码

    def _ls(self, header_dic):
        """查看当前目录"""
        # 执行终端命令,并获取结果
        obj = subprocess.Popen("dir %s" % self.current_dir, shell=True,
                               stdout = subprocess.PIPE,
                               stderr = subprocess.PIPE)
        stdout = obj.stdout.read()
        stderr = obj.stderr.read()

        self.send_response(status_code=300, size=len(stdout)+len(stderr), current_dir=self.current_dir) # 当前目录为断点续存做准备

        # 发送执行结果
        self.conn.send(stderr)
        self.conn.send(stdout)

查看客户端目录

客户端 server 文件夹下 FTPClient.py

 def dir(self, command):
        """查看客户端下的目录"""
        # 由于是查看客户端目录,所以可以不输入路径或是输入路径,即传入的参数最多为 1,1 是目录路径
        if self.parameter_length_judgment(command, most_size=1):
            if command: # 如果 command 不为空
                path = command[0]
            else:
                path = ""
            # 执行终端命令
            obj = subprocess.Popen("dir %s" % path, shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
            stdout = obj.stdout.read()
            stderr = obj.stderr.read()

            print(stdout.decode("gbk"), stderr.decode("gbk"))

切换目录

客户端 server 文件夹下 FTPClient.py

    def cd(self, command):
        """切换服务端目录"""
        # 切换服务端目录,所以必须输入路径,即传入的参数最少为 1,1 是目录路径,多于 1 的部分不需要考虑
        if self.parameter_length_judgment(command, most_size=1):
            cmd = command[0]
            self.create_header_send(action_type="cd", cmd=cmd)
            # 获取 response
            response = self.get_response()

            if response.get("status_code") == 300:
                show_to_client = response.get("show_to_client")
                self.show_to_client = "[%s]" % show_to_client
                self.current_dir = response.get("current_dir")
            else:
                print(response.get("status_msg"))

服务端 lib 文件夹下 main.py

    def _cd(self, header_dic):
        """切换目录,但最高一级只到 \\home\\username"""
        cmd = header_dic.get("cmd")
        full_path = os.path.abspath(os.path.join(self.current_dir, cmd)) # 拼接路径,返回绝对路径,避免出现 \\home\\username\\..\\.. 的情况出现

        if os.path.isdir(full_path): # 如果路径存在
            if full_path.replace(self.user_home, "") and self.user_home in full_path: # 保证路径不会到达 home 一级
                obj = subprocess.Popen("cd %s" % full_path, shell=True,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE)
                self.current_dir = full_path
                self.send_response(status_code=300,
                                   show_to_client = full_path.replace(self.user_home, ""),
                                   current_dir=self.current_dir)  # 当前目录为断点续存做准备
            else:
                self.send_response(status_code=301)  # 对用户来说路径不存在
        else:
            self.send_response(status_code=301) # 对用户来说路径不存在

运行结果


文章作者: New Ass
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 New Ass !
  目录