每日一题.基于SocketServer面向对象编写支持多路IO的FTPServer服务器?

代码流程:

每日一题.基于SocketServer面向对象编写支持多路IO的FTPServer服务器?_第1张图片


目录结构 - FtpServer:

|-- ftpserver

|   |-- conf

|   |   |-- ftpserver.conf

|   |   `-- ftpusers.conf

|   |-- data

|   |   |-- anonymous

|   |   |-- pub

|   |   |   `-- test.txt

|   |   `-- root

|   |       `-- XX00

|   |           |-- limanman

|   |           `-- xx

|   |-- __init__.py

|   |-- __init__.pyc

|   |-- logs

|   `-- modules

|       |-- FtpServer.py

|       |-- FtpServer.pyc

|       |-- __init__.py

|       `-- __init__.pyc

|-- server.py


目录结构 - FtpClient:

|-- client.py

|-- ftpclient

|   |-- data

|   |   |-- xx

|   |   |-- xx.0

|   |   |-- xx.0.0

|   |   |-- xx.1

|   |   |-- xx.2

|   |   |-- xx.3

|   |   |-- xx.4

|   |   |-- xx.5

|   |   |-- xx.6

|   |   |-- xx.7

|   |   `-- xx.8

|   |-- __init__.py

|   |-- __init__.pyc

|   `-- modules

|       |-- FtpClient.py

|       |-- FtpClient.pyc

|       |-- __init__.py

|       `-- __init__.pyc


相关配置 - FtpServer:

/xm-workspace/xm-pyss/auto_python/xmdevops_limanman/ftpserver/conf/ftpserver.conf

# basic server setting
ftp_listen_port = 21

ftp_login_banner = 欢迎访问 XmDevOps FTPserver!

ftp_logout_banner = 再见!

ftp_access_dir =

# basic private setting

ftp_download_file = True

ftp_upload_file = True

ftp_rename_file = True

ftp_delete_file = True

ftp_create_dir = True

ftp_anonymous_access = True

 /xm-workspace/xm-pyss/auto_python/xmdevops_limanman/ftpserver/conf/ftpusers.conf

root = root


代码实现 - FtpServer:

/xm-workspace/xm-pyss/auto_python/xmdevops_limanman/server.py:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import os
import pprint
from ftpserver.modules.FtpServer import (FtpServer, FtpHandler)


def read_conf(conf):
    """Read conf file.

    Args:
        conf: ftp server conf
    Returns:
        dict
    """
    # 配置文件错误检测略
    conf_dict = {}
    with open(conf, 'r+b') as rhandler:
        for cur_line in rhandler:
            cur_line = cur_line.strip()
            if cur_line.startswith('#') or ('=' not in cur_line):
                continue
            key = cur_line.split('=')[0].strip()
            val = cur_line.split('=')[1].strip()
            conf_dict.update({key: val})
    return conf_dict

def get_dirs(*args):
    """Get dirs.

    Args:
        args: dir list
    Returns:
        dict
    """
    ftp_dirs = {}
    for cur_dir in args:
        ftp_dirs.update({
            cur_dir: os.path.join(os.getcwd(),'ftpserver',cur_dir)
        })
    return ftp_dirs

def main():
    """Main function.
    """
    host_info = ('', int(ftp_conf['ftp_listen_port']))
    setattr(FtpHandler, 'ftp_dirs', ftp_dirs)
    setattr(FtpHandler, 'ftp_conf', ftp_conf)
    setattr(FtpHandler, 'ftp_user', ftp_user)
    server = FtpServer(host_info, FtpHandler)
    server.serve_forever()

if __name__ == "__main__":
    # 读取当前的目录和配置
    ftp_dirs = get_dirs('conf', 'logs', 'data', 'modules')
    ftp_conf = read_conf(os.path.join(ftp_dirs['conf'], 'ftpserver.conf'))
    ftp_user = read_conf(os.path.join(ftp_dirs['conf'], 'ftpusers.conf'))

    # 更改默认程序运行目录
    if ftp_conf.has_key('ftp_access_dir'):
        if not ftp_conf['ftp_access_dir'].strip():
            ftp_conf['ftp_access_dir'] = os.path.join(ftp_dirs['data'], 'pub')

    # 运行
    main()

/xm-workspace/xm-pyss/auto_python/xmdevops_limanman/ftpserver/modules/FtpServer.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import os
import time
import glob
import shutil
from SocketServer import (StreamRequestHandler, ThreadingMixIn, TCPServer)


# 装饰 - 判断是否已登陆
def ftp_is_login(func):
    """Common login verification decorate.

    Args:
        func: ftp action.
    Returns:
        func
    """
    def decorate(self, *args):
        # 登陆验证
        if not self.login_usr:
            self.wfile.write('errors: login with username'
                             'and user pass first.%s' % (os.linesep))
            return False
        # 参数验证
        if args[0][0] != 'ftp_disconnect':
            if not args[0][1].strip():
                self.wfile.write('errors: detected parameter '
                                 'is empty with error.%s' % (os.linesep))
                return False
        func_res = func(self, *args)
        return func_res
    return decorate

# 多线程处理多路IO
class FtpServer(ThreadingMixIn, TCPServer):
    """Multiplex threading io class.
    """
    pass

# 多路IO处理类
class FtpHandler(StreamRequestHandler):
    """Multiplex threading io request handler class.

    Attrinutes:
        exit_flag: is exit?
        login_usr: curent login user.
        directory: current directory
    """
    login_usr = None
    directory = None
    exit_flag = False

    @staticmethod
    def add_ends(command):
        """Add linesep for command.

        Args:
            command: command string
        Returns:
            string
        """
        return '%s%s' % (command, os.linesep)

    # 主要处理方法
    def handle(self):
        while not self.exit_flag:
            # 启动界面
            if not self.login_usr:
                self.wfile.write('%s%s' % (self.ftp_conf['ftp_login_banner'],
                                           os.linesep))
                self.wfile.write('User (%s:(none)): ' % self.client_address[0])
                user_name = self.rfile.readline().strip()
                self.wfile.write('Please specify the password.%s' % os.linesep)
                self.wfile.write('Password: ')
                user_pass = self.rfile.readline().strip()
                self.ftp_authentication(['ftp_authentication',
                                         user_name,user_pass])
            # 命令执行
            self.wfile.write('ftp> ')
            cur_buffer = self.rfile.readline().strip()
            parameters = cur_buffer.split('|')
            cur_action = parameters[0]
            if hasattr(self, cur_action):
                func = getattr(self, cur_action)
                # parameters返回给客户端时会用到
                func_res = func(parameters)
                # 防止指令参数为空导致异常友好提示
                if not func_res:
                    continue
                self.wfile.write(func_res)
            else:
                self.wfile.write('errors: get wrong'
                                 'message type (%s)%s' % (cur_action,
                                                          os.linesep))

    # FTP授权访问方法
    def ftp_authentication(self, parameters):
        """Ftp authentication.

        Args:
            parameters: parameters list
        Returns:
            ftp_authentication::flag::describe
        msgformat:
            ftp_authentication|uname|upass
        """
        # 登陆验证,格式已定
        action_res = False
        action, uname, upass = parameters
        authentication_res = '%s::0::ftp authentication fail.' % (action)

        if uname == 'anonymous':
            action_res = True
        if self.ftp_user.has_key(uname) and self.ftp_user[uname] == upass:
            action_res = True

        if action_res:
            authentication_res = '%s::1::ftp authentication succ.' % (action)
            self.directory = os.path.join(self.ftp_dirs['data'], uname)
            if not os.path.exists(self.directory):
                os.makedirs(self.directory)
            # 代表已登陆
            self.login_usr = uname
        self.wfile.write(self.add_ends(authentication_res))
        return action_res

    # FTP显示当前路径
    @ftp_is_login
    def ftp_showpwd(self, parameters):
        """Ftp change dir

        Args:
            parameters: ['.']
        Returns:
            ftp_showpwd::dstdir::flag::describe
        msgformat:
            ftp_showpwd|.
        """
        action, dstdir = parameters
        showpwd_res = '%s::%s::1::%s' % (action, dstdir, self.directory)
        return self.add_ends(showpwd_res)

    # FTP切换目录方法
    @ftp_is_login
    def ftp_changedir(self, parameters):
        """Ftp change dir

        Args:
            parameters: parameters list
        Returns:
            ftp_changedir::dstdir::flag::describe
        msgformat:
            ftp_changedir|dstdir
        """
        # 登陆验证,格式已定
        action_res = False
        action, dstdir = parameters
        changedir_res = '%s::%s::0::ftp changedir fail.' % (action, dstdir)
        cur_dir = os.path.join(self.directory, dstdir)
        cur_dir = os.path.abspath(cur_dir)
        # 限制用户在家目录
        if os.path.exists(cur_dir) and os.path.isdir(cur_dir):
            if cur_dir in self.ftp_dirs['data']:
                cur_dir = self.directory
            action_res = True

        if action_res:
            changedir_res = '%s::%s::0::ftp changedir succ.' % (action, dstdir)
            os.chdir(cur_dir)
            self.directory = cur_dir
        return self.add_ends(changedir_res)

    @staticmethod
    def show_fileattr(cur_file):
        """Show file attribute.

        Args:
            cur_file: file with abs path.
        Returns:
            str
        """
        mode_dict = {
            '1': '--x',
            '2': '-w-',
            '4': 'r--',
            '5': 'r-x',
            '6': 'rw-',
            '7': 'rwx',
        }
        file_type = 'f'
        file_mode = ''
        file_stat = os.stat(cur_file)
        file_moct = oct(file_stat.st_mode)[-3:]
        file_link = file_stat.st_nlink
        file_size = file_stat.st_size
        file_name = os.path.basename(cur_file)
        file_time = time.ctime(file_stat.st_mtime)

        if os.path.isdir(cur_file):
            file_type = 'd'
        for cur_bit in file_moct:
            file_mode += mode_dict[cur_bit]

        return '%s%s %s user group %-10s %-10s %s' % (file_type, file_mode,
                                                      file_link, file_size,
                                                      file_time, file_name)

    # FTP列出文件方法
    @ftp_is_login
    def ftp_listfile(self, parameters):
        """Ftp list files.

        Args:
            parameters: parameters list
        Returns:
            ftp_listfile::dstdir::flag::describe
        msgformat:
            ftp_listfile|dstdir
        """
        # 登陆验证,格式已定
        attrs_list = []
        action_flag = False
        action, dstdir = parameters
        cur_dir = os.path.join(self.directory, dstdir)
        cur_dir = os.path.abspath(cur_dir)
        listfile_res = 'ftp_listfile::%s:0::ftp listfile fail.' % (dstdir)
        if not os.path.isdir(cur_dir):
            return self.add_ends(listfile_res)
        if cur_dir in self.ftp_dirs['data']:
            cur_dir = self.directory
        for cur_file in os.listdir(cur_dir):
            abs_path = os.path.join(cur_dir, cur_file)
            cur_line = self.show_fileattr(abs_path)
            attrs_list.append(cur_line)
        return self.add_ends(os.linesep.join(attrs_list))

    # FTP下载文件方法
    def ftp_download(self, parameters):
        """Ftp download.

        Args:
            parameters: [action, fname]
        Returns:
            ftp_download::fname::flag::describe
        msgformat:
            ftp_download|fname|fsize
        """
        action, fname = parameters
        freal_path = os.path.join(self.directory, fname)
        download_res = ('ftp_download::%s::%s::0::ftp '
                        'download fail.' % (fname, 0))
        if os.path.exists(freal_path) and os.path.isfile(freal_path):
            fsize = os.path.getsize(freal_path)
            # 告诉客户端文件名和文件大小
            download_res = ('ftp_download::%s::%s::1::ftp '
                            'download ready' % (fname, fsize))
            self.wfile.write(self.add_ends(download_res))
            rhandler = open(freal_path, 'r+b')
            cur_send = 0
            while cur_send != int(fsize):
                splus = fsize - cur_send
                if splus <= 1024:
                    cur_buffer = rhandler.read(splus)
                    cur_send += splus
                else:
                    cur_buffer = rhandler.read(1024)
                    cur_send += 1024
                self.wfile.write(cur_buffer)
            if not rhandler.closed:
                rhandler.close()
            download_res = ('ftp_download::%s::%s::1::ftp '
                            'download succ.' % (fname, fsize))
        return self.add_ends(download_res)

    @staticmethod
    def file_suffix(fname, fpath):
        """Got file suffix.
        Args:
            fname: file name
            fpath: file dir path
        Returns:
            str
        """
        suffix_res = fname
        real_path = os.path.join(fpath, fname)
        glob_path = os.path.join(fpath, '%s.*' % (fname))
        # 如果文件存在获取编号
        if os.path.exists(real_path):
            glob_file = glob.glob(glob_path)
            if not glob_file:
                suffix_res = '%s.0' % (fname)
            else:
                glob_file.sort(key=lambda s:int(s[-1]), reverse=True)
                suffix_res = '%s.%s' % (fname, int(glob_file[0][-1])+1)
        return os.path.join(fpath, suffix_res)

    # FTP上传文件方法
    @ftp_is_login
    def ftp_upload(self, parameters):
        """Ftp upload.

        Args:
            parameters: [action, fname, fsize]
        Returns:
            ftp_upload::fname::flag::describe
        msgformat:
            ftp_upload|fname|fsize
        """
        # 登陆验证,格式已定
        action, fname, fsize = parameters
        upload_res = 'ftp_upload::%s::0::ftp upload fail.' % (fname)
        file_path = os.path.join(self.directory, fname)
        file_back = self.file_suffix(fname, self.directory)
        ahandler = open(file_back, 'a+b')
        cur_recv = 0
        while cur_recv != int(fsize):
            cur_buffer = self.request.recv(1024)
            cur_recv += len(cur_buffer)
            ahandler.write(cur_buffer)
        if not ahandler.closed:
            ahandler.close()
        upload_res = 'ftp_upload::%s::1::ftp upload succ.' % (fname)
        return self.add_ends(upload_res)

    # FTP文件更名方法
    @ftp_is_login
    def ftp_rename(self, parameters):
        """Ftp rename.
        Args:
            parameters: [sfname, dsname]
        Returns:
            ftp_rename::sfname::dfname::flag::describe
        msgformat:
            ftp_delete|sfname|dfname
        """
        action, sfname, dfname = parameters
        rename_res = 'ftp_rename::%s::%s::0::ftp rename fail.' % (sfname,
                                                                  dfname)
        sreal_path = os.path.join(self.directory, sfname)
        dreal_path = os.path.join(self.directory, dfname)
        if os.path.exists(sreal_path):
            rename_res = 'ftp_rename::%s::%s::1::ftp rename succ.' % (sfname,
                                                                      dfname)
            shutil.move(sreal_path, dreal_path)
        return self.add_ends(rename_res)

    # FTP删除文件方法
    @ftp_is_login
    def ftp_delete(self, parameters):
        """Frp delete
        Args:
            parameters: [fname]
        Returns:
            ftp_delete::fname::flag::describe
        msgformat:
            ftp_delete|fname
        """
        action, fname = parameters
        rpath = os.path.join(self.directory, fname)
        delete_res = 'ftp_delete::%s::0::ftp delete fail.' % (fname)
        if os.path.exists(rpath):
            if os.path.isfile(rpath):
                os.remove(rpath)
            else:
                shutil.rmtree(rpath)
            delete_res = 'ftp_delete::%s::1::ftp delete succ.' % (fname)
        return self.add_ends(delete_res)

    # FTP创建目录方法
    @ftp_is_login
    def ftp_createdir(self, parameters):
        """Ftp createdir.

        Args:
            parameters: [dname]
        Returns:
            ftp_createdir::dname::flag::describe
        msgformat:
            ftp_createdir|dname
        """
        action, dname = parameters
        createdir_res = 'ftp_createdir::%s::0::ftp createdir fail.' % (dname)
        real_path = os.path.join(self.directory, dname)
        os.makedirs(real_path)
        createdir_res = 'ftp_createdir::%s::1::ftp createdir succ.' % (dname)
        return self.add_ends(createdir_res)

    # FTP关闭连接方法
    @ftp_is_login
    def ftp_disconnect(self, parameters):
        """Ftp disconnect.

        Args:
            parameters: default empty
        Returns:
            ftp_disconnect::flag::describe
        msgformat:
            ftp_disconnect
        """
        action = parameters[0]
        disconnect_res = '%s::0::ftp disconnect fail.' % (action)

        self.exit_flag = True
        if self.exit_flag:
            disconnect_res = '%s::1::ftp disconnect succ.' % (action)

        # 发送执行结果
        return self.add_ends(disconnect_res)


代码实现 - FtpClient:

/xm-workspace/xm-pyss/auto_python/xmdevops_limanman/client.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import os
import sys
import pprint
import socket
from ftpclient.modules.FtpClient import FtpClient


def main():
    """Main function.
    """
    curdata_dir = os.path.join(os.getcwd(), 'ftpclient', 'data')
    others_dict = {
        'data' : curdata_dir,
    }
    action_dict = {
        'dir'  : 'ftp_listfile',
        'cd'   : 'ftp_changedir',
        'get'  : 'ftp_download',
        'put'  : 'ftp_upload',
        'mv'   : 'ftp_rename',
        'pwd'  : 'ftp_showpwd',
        'del'  : 'ftp_delete',
        'mkdir': 'ftp_createdir',
        'bye'  : 'ftp_disconnect',
        'quit' : 'ftp_disconnect'
    }

    FtpClient(action_dict, others_dict, '127.0.0.1', 21)

if __name__ == '__main__':
    main()

/xm-workspace/xm-pyss/auto_python/xmdevops_limanman/ftpclient/modules/FtpClient.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://my.oschina.net/pydevops/
# Purpose:
#
"""
import os
import sys
import glob
import socket


class FtpClient(object):
    """Ftp client class.

    Attributes:
        conn_host  : ftp server host
        conn_port  : ftp server port
        action_dict: ftp client action dict
    """
    actionres_dict = {}

    @staticmethod
    def add_ends(command):
        return '%s%s' % (command, os.linesep)

    def __init__(self, action_dict, others_dict,
                 conn_host='127.0.0.1', conn_port=21):
        self.conn_host = conn_host
        self.conn_port = conn_port
        self.others_dict = others_dict
        self.action_dict = action_dict
        self.cursocket = self.ftp_connect(self.conn_host,
                                          self.conn_port)

        # 切换到进程目录
        os.chdir(self.others_dict['data'])

        while True:
            # 没数据会阻塞在这里
            cur_buffer = self.cursocket.recv(1024)
            action_res = cur_buffer.split('::')
            if action_res[0] == 'ftp_disconnect':
                break
            # 结果保存后续再处理
            if 'User' in cur_buffer or 'Password' in cur_buffer:
                user_info = raw_input(cur_buffer)
                user_info = self.add_ends(user_info)
                self.cursocket.sendall(user_info)
            elif 'ftp>' in cur_buffer:
                comm_strs = raw_input(cur_buffer)
                comm_strs = self.add_ends(comm_strs)
                comm_list = comm_strs.split()
                # 防止空输入的异常
                if not comm_list:
                    self.cursocket.sendall(os.linesep)
                    continue
                # 获取当前调用方法
                curaction = comm_list[0]
                curparses = comm_list[1:]
                if not self.action_dict.has_key(curaction):
                    self.cursocket.sendall(comm_strs)
                else:
                    func = getattr(self, self.action_dict[curaction])
                    func(curparses)
                continue
            else:
                # 处理返回值
                if '::' in cur_buffer:
                    self.actionres_dict.update({action_res[0]: action_res[1:]})
                sys.stdout.write(cur_buffer)
                sys.stdout.flush

    def ftp_connect(self, conn_host, conn_port):
        """Ftp connect

        Args:
            conn_host: ftp server host
            conn_port: ftp client port
        Returns:
            socket
        """
        try:
            cur_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            # 端口复用和长连接
            cur_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            # cur_socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
        except socket.error, e:
            sys.exit('errors: creating socket with error %s' % (e))

        try:
            cur_socket.connect((conn_host, conn_port))
        except socket.gaierror, e:
            sys.exit('errors: resolve host with error %s' % (e))
        except socket.error, e:
            sys.exit('errors: connection host with error %s' % (e))
        # 返回socket句柄
        return cur_socket

    # FTP显示当前路径
    def ftp_showpwd(self, parameters):
        """Ftp showpwd.

        msgformat:
            ftp_showpwd|.
        """
        res_parameters = self.add_ends('.')
        self.cursocket.sendall('ftp_showpwd|%s' % (res_parameters))


    # FTP列出文件方法
    def ftp_listfile(self, parameters):
        """Ftp listfile.

        msgformat:
            ftp_listfile|dstdir
        """
        res_parameters = self.add_ends(''.join(parameters))
        self.cursocket.sendall('ftp_listfile|%s' % (res_parameters))

    # FTP改变目录方法
    def ftp_changedir(self, parameters):
        """Ftp change directory.

        msgformat:
            ftp_changedir|dstdir
        """
        res_parameters = self.add_ends(''.join(parameters))
        self.cursocket.sendall('ftp_changedir|%s' % (res_parameters))

    @staticmethod
    def file_suffix(fname, fpath):
        """Got file suffix.
        Args:
            fname: file name
            fpath: file dir path
        Returns:
            str
        """
        suffix_res = fname
        real_path = os.path.join(fpath, fname)
        glob_path = os.path.join(fpath, '%s.*' % (fname))
        # 如果文件存在获取编号
        if os.path.exists(real_path):
            glob_file = glob.glob(glob_path)
            if not glob_file:
                suffix_res = '%s.0' % (fname)
            else:
                glob_file.sort(key=lambda s:int(s[-1]), reverse=True)
                suffix_res = '%s.%s' % (fname, int(glob_file[0][-1])+1)
        return os.path.join(fpath, suffix_res)

    # FTP下载文件方法
    def ftp_download(self, parameters):
        """Ftp download.

        msgformat:
            ftp_download|fname
        """
        fname = parameters[0]
        res_download = self.add_ends('%s' % (fname))
        self.cursocket.sendall('ftp_download|%s' % (res_download))
        while True:
            cur_buffer = self.cursocket.recv(1024)
            if '::' in cur_buffer:
                fsize = int(cur_buffer.split('::')[2])
                break
        suffixname = self.file_suffix(fname, self.others_dict['data'])
        whanler = open(suffixname, 'a+b')
        cur_recv = 0
        while cur_recv != fsize:
            cur_buffer = self.cursocket.recv(1024)
            cur_recv += len(cur_buffer)
            whanler.write(cur_buffer)
        if not whanler.closed:
            whanler.close()

    # FTP上传文件方法
    def ftp_upload(self, parameters):
        """Ftp upload.

        msgformat:
            ftp_upload|fname|fsize
        """
        fname = parameters[0]
        rpath = os.path.join(self.others_dict['data'], fname)
        if os.path.exists(rpath) and os.path.isfile(rpath):
            fsize = os.path.getsize(rpath)
            res_parameters = self.add_ends('%s|%s' % (fname, fsize))
            self.cursocket.sendall('ftp_upload|%s' % (res_parameters))
            rhandler = open(rpath, 'r+b')
            cur_send = 0
            while cur_send != int(fsize):
                splus = fsize - cur_send
                if splus <= 1024:
                    cur_data = rhandler.read(splus)
                    cur_send += splus
                else:
                    cur_data = rhandler.read(1024)
                    cur_send += 1024
                self.cursocket.sendall(cur_data)
            if not rhandler.closed:
                rhandler.close()
        else:
            print 'errors: read file %s with errors' % (fname)


    # FTP文件命名方法
    def ftp_rename(self, parameters):
        """Ftp rename

        msgformat:
            ftp_rename|sfname|dfname
        """
        res_parameters = self.add_ends('|'.join(parameters))
        self.cursocket.sendall('ftp_rename|%s' % (res_parameters))

    # FTP文件删除方法
    def ftp_delete(self, parameters):
        """Frp delete

        msgformat:
            ftp_delete|fname
        """
        res_parameters = self.add_ends(''.join(parameters))
        self.cursocket.sendall('ftp_delete|%s' % (res_parameters))

    # FTP创建目录方法
    def ftp_createdir(self, parameters):
        """Ftp createdir.

        msgformat:
            ftp_createdir|dname
        """
        res_parameters = self.add_ends(''.join(parameters))
        self.cursocket.sendall('ftp_createdir|%s' % (res_parameters))

    # FTP关闭连接方法
    def ftp_disconnect(self, parameters):
        """Ftp disconnect.

        msgformat:
            ftp_disconnect
        """
        action_res = False
        res_parameters = self.add_ends('ftp_disconnect')
        self.cursocket.sendall(res_parameters)
        return action_res


有图有像:

每日一题.基于SocketServer面向对象编写支持多路IO的FTPServer服务器?_第2张图片


你可能感兴趣的:(每日一题.基于SocketServer面向对象编写支持多路IO的FTPServer服务器?)