功能: 
1、用户加密认证
2、允许同时多用户登录
3、每个用户有自己的家目录 ,且只能访问自己的家目录
4、对用户进行磁盘配额,每个用户的可用空间不同
5、允许用户在ftp server上随意切换目录
6、允许用户查看当前目录下文件
7、允许上传和下载文件,保证文件一致性
8、文件传输过程中显示进度条
附加功能:支持文件的断点续传 环境
  python 3.5 特性:
  用socketserver实现FTP 主要功能实现:
  1、用户加密认证
    ConfigParser 是Python自带的模块, 用来读写配置文件,将用户信息以下边的格式存入account.py文件,读出后进行判断
[DEFAULT]

[alex]
Password = 123456
Quotation = 100 [jack]
Password = 123456
Quotation = 100
    2、允许同时多用户登录
      从scokerserver 继承 socketserver.ThreadingTCPServer即可实现
    3、每个用户有自己的家目录 ,且只能访问自己的家目录
      将所有路径封装在home目录下
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

USER_HOME = '%s\home' % BASE_DIR
LOG_DIR = '%s\log' % BASE_DIR
LOG_LEVEL = 'DEBUG'
    4、允许用户在ftp server上随意切换目录
      用os模块改变工作目录
os.chdir(func_val)
    5、允许用户查看当前目录下文件
      用os模块的os.listdir,下为server端代码
    def _ls(self,*args,**kwargs):
'''显示当前目录下的所有文件'''
if os.getcwd() == '%s\\bin'% settings.BASE_DIR:
user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
self.request.send(json.dumps(os.listdir(user_home_dir)).encode())
else:self.request.send(json.dumps(os.listdir()).encode())
    6、允许上传和下载文件,保证文件一致性
      判断上传和下载的文件在传输前后的大小,用以判断文件是否保持一致
 #server端
#
def _put(self,*args,**kwargs):
'''上传文件命令'''
data = args[0] response = self.get_response()
if response["status_code"] == 257: # ready to receive
self.request.send(b'') # send confirmation to server
user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
base_filename = "%s\%s" % (user_home_dir, data.get('filename'))
received_size = 0
file_obj = open(base_filename, 'wb')
if data.get('md5'):
md5_obj = hashlib.md5()
while received_size < response['file_size']:
line = self.request.recv(4096)
received_size += len(line)
file_obj.write(line)
md5_obj.update(line)
else:
file_obj.close()
md5_val = md5_obj.hexdigest()
self.send_response(258, {'md5': md5_val})
print("-----file rece done-----") else:
while received_size < response['file_size']:
data = self.request.recv(4096)
received_size += len(data)
file_obj.write(data)
else:
print("-----file rece done-----")
file_obj.close()
else:
print(STATUS_CODE[response["status_code"]]) def _get(self,*args,**kwargs):
'''下载文件命令'''
data = args[0]
if data.get('filename') is None:
self.send_response(255)
user_home_dir = "%s\%s" %(settings.USER_HOME,self.user["Username"])
file_abs_path = "%s\%s" %(user_home_dir,data.get('filename'))
print("file abs path",file_abs_path) if os.path.isfile(file_abs_path):
file_obj = open(file_abs_path,'rb')
file_size = os.path.getsize(file_abs_path)
self.send_response(257,data = {'file_size':file_size})
self.request.recv(1) #等待客户端确认,防粘包 if data.get('md5'):
md5_obj = hashlib.md5()
for line in file_obj:
self.request.send(line)
md5_obj.update(line)
else:
file_obj.close()
md5_val = md5_obj.hexdigest()
self.send_response(258,{'md5':md5_val})
print("send file done...")
else:
for line in file_obj:
self.request.send(line)
else:
file_obj.close()
print("send file done...")
else:
self.send_response(256) # client端
#
def _get(self,cmd_list):
'''下载文件'''
print("get--",cmd_list)
if len(cmd_list) == 1:
print("no filename follows...")
return
data_header = {
'action':'get',
'filename':cmd_list[1]
}
if self.__md5_required(cmd_list):
data_header['md5'] = True self.sock.send(json.dumps(data_header).encode())
response = self.get_response()
print(response)
try:
if response["status_code"] == 257:#ready to receive
self.sock.send(b'') #send confirmation to server
base_filename = cmd_list[1].split('/')[-1]
received_size = 0
file_obj = open(base_filename,'wb')
if self.__md5_required(cmd_list):
md5_obj = hashlib.md5()
progress = self.show_progress(response['file_size']) #generator
progress.__next__()
while received_size < response['file_size']:
data = self.sock.recv(4096)
received_size += len(data)
try:
progress.send(len(data))
except StopIteration as e:
print("100%")
file_obj.write(data)
md5_obj.update(data)
else:
print("-----file rece done-----")
file_obj.close()
md5_val = md5_obj.hexdigest()
md5_from_server = self.get_response()
if md5_from_server['status_code'] == 258:
if md5_from_server['md5'] == md5_val:
print("%s 文件一致性校验成功!"% base_filename)
print(md5_val,md5_from_server) else:
progress = self.show_progress(response['file_size']) # generator
progress.__next__()
while received_size < response['file_size']:
data = self.sock.recv(4096)
received_size += len(data)
file_obj.write(data)
try:
progress.send(len(data))
except StopIteration as e:
print("100%")
else:
print("-----file rece done-----")
file_obj.close()
else:
print(STATUS_CODE[response["status_code"]])
except Exception as e:
base_file_size = os.path.getsize(base_filename)
with open('data\\breakpoint', 'wb') as br_po:
data_header['action'] = 'breakpoint'
data_header['breakpoint'] = base_file_size
br_po.write(json.dumps(data_header).encode()) def _put(self,cmd_list):
'''上传文件'''
print("put--", cmd_list)
if len(cmd_list) == 1:
print("no filename follows...")
return
data_header = {
'action': 'put',
'filename': cmd_list[1]
}
if self.__md5_required(cmd_list):
data_header['md5'] = True self.sock.send(json.dumps(data_header).encode())
if os.path.isfile(cmd_list[1]):
file_obj = open(cmd_list[1], 'rb')
file_size = os.path.getsize(cmd_list[1])
self.send_response(257, data={'file_size': file_size})
self.sock.recv(1) # 等待服务器端确认
if self.__md5_required(cmd_list):
md5_obj = hashlib.md5()
progress = self.show_progress(file_size) # generator
progress.__next__()
for line in file_obj:
self.sock.send(line)
try:
progress.send(len(line))
except StopIteration as e:
print("100%")
md5_obj.update(line)
else:
file_obj.close()
md5_val = md5_obj.hexdigest()
md5_from_server = self.get_response()
if md5_from_server['md5'] == md5_val:
print("%s 文件一致性校验成功!"% cmd_list[1])
self.send_response(258, {'md5': md5_val})
print("send file done...")
else:
progress = self.show_progress(file_size) # generator
progress.__next__()
for line in file_obj:
self.sock.send(line)
try:
progress.send(len(line))
except StopIteration as e:
print("100%")
else:
file_obj.close()
print("send file done...")
else:
print(256)

get and put

    7、文件传输过程中显示进度条
      根据已传文件大小和总文件大小比对判断,输出符号
     def show_progress(self,total):
'''显示进度条
total: 文件大小'''
received_size = 0
current_percent = 0
while received_size < total:
if int((received_size / total) * 100) > current_percent:
print(">",end='',flush=True)
current_percent = int((received_size / total) * 100)
new_size = yield
received_size += new_size

进度条

    附加功能:支持文件的断点续传
      将上次断点信息记录下来,也就是记录已传文件大小,再次启用时,将目标文件光标移到上次断点处,然后进行续传
     def _breakpoint(self,*args,**kwargs):
'''断点续传'''
data = args[0]
if data.get('filename') is None:
self.send_response(255)
user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
file_abs_path = "%s\%s" % (user_home_dir, data.get('filename'))
print("file abs path", file_abs_path)
print(data.get('breakpoint')) if os.path.isfile(file_abs_path):
file_obj = open(file_abs_path, 'rb')
file_obj.seek(data.get('breakpoint'))
file_size = os.path.getsize(file_abs_path)
self.send_response(257, data={'file_size': file_size})
self.request.recv(1) # 等待客户端确认 if data.get('md5'):
md5_obj = hashlib.md5()
for line in file_obj:
self.request.send(line)
md5_obj.update(line)
else:
file_obj.close()
md5_val = md5_obj.hexdigest()
self.send_response(258, {'md5': md5_val})
print("send file done...")
else:
for line in file_obj:
self.request.send(line)
else:
file_obj.close()
print("send file done...")
else:
self.send_response(256)
pass

breakpoint

   主要知识点:

    类的继承
os模块的应用
json模块的应用
类方法的运用
md5加密方法
scoket链接
scoketserver链接
反射
异常处理 小结:
这个程序主要用socketserver实现了一台服务器链接多个客户端,并且进行信息交互,并且实现了几个简单的功能,如:get 文件下载、put 上传文件、cd 切换目录、ls 查看文件、breakpoint断点续传。 主要代码:
 #server端
# import os,sys
import hashlib
import socket
import socketserver
import json
import configparser
from conf import settings STATUS_CODE = {
250 : "Invalid cmd format,e.g:{'action':'get','filename':'test.py','size':344",
251 : "Invalid cmd",
252 : "Invalid auth data",
253 : "Wrong username or password..",
254 : "Passed authentication",
255 : "Filename doesn't provided",
256 : "File doesn't exist on server",
257 : "ready to send file",
258 : "md5 verification",
259 : "Directory has been switched"
} class FTPHandler(socketserver.BaseRequestHandler):
'''定义request handler类,从BaseRequestHandler类继承'''
def handle(self):
'''
获取服务器端的信息
如果传来cd命令,改变工作目录
''' while True:
self.data = self.request.recv(1024).strip()
if not self.data:
print('Client closed..')
break
data = json.loads(self.data.decode())
if data.get('action') is not None:
if hasattr(self,'_%s'%data.get('action')):
func =getattr(self,'_%s'%data.get('action'))
func_val = func(data)
if data.get('action') == 'cd': #cd 命令,改变工作目录
os.chdir(func_val)
else:pass
else:
print('Invalid cmd')
self.send_response(251)
else:
print('Invalid cmd format')
self.send_response(250) def send_response(self,status_code,data=None):
'''向客户端返回数据'''
response = {'status_code': status_code, 'status_msg':STATUS_CODE[status_code]}
if data:
response.update(data)
self.request.send(json.dumps(response).encode()) def _auth(self,*args,**kwargs):
'''判断用户是否输入完整的用户名和密码
验证用户名和密码是否合法'''
data = args[0]
if data.get('username') is None or data.get('password') is None:
self.send_response(252) user = self.authenticate(data.get('username'),data.get('password'))
if user is None:
self.send_response(253)
else:
print('passed authentication',user)
self.user = user
self.send_response(254) def authenticate(self,username,password): #
'''验证用户合法性,合法返回用户数据'''
config = configparser.ConfigParser()
config.read(settings.ACCOUNT_FILE)
if username in config.sections():
_password = config[username]['Password']
if _password == password:
print('pass auth..',username)
config[username]["Username"] = username
return config[username] def get_response(self):
'''接收客户端回复结果'''
data = self.request.recv(1024)
data = json.loads(data.decode())
return data def show_progress(self,total):
'''显示进度条
total: 文件大小'''
received_size = 0
current_percent = 0
while received_size < total:
if int((received_size / total) * 100) > current_percent:
print(">",end='',flush=True)
current_percent = int((received_size / total) * 100)
new_size = yield
received_size += new_size def _put(self,*args,**kwargs):
'''上传文件命令'''
data = args[0] response = self.get_response()
if response["status_code"] == 257: # ready to receive
self.request.send(b'') # send confirmation to server
user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
base_filename = "%s\%s" % (user_home_dir, data.get('filename'))
received_size = 0
file_obj = open(base_filename, 'wb')
if data.get('md5'):
md5_obj = hashlib.md5()
while received_size < response['file_size']:
line = self.request.recv(4096)
received_size += len(line)
file_obj.write(line)
md5_obj.update(line)
else:
file_obj.close()
md5_val = md5_obj.hexdigest()
self.send_response(258, {'md5': md5_val})
print("-----file rece done-----") else:
while received_size < response['file_size']:
data = self.request.recv(4096)
received_size += len(data)
file_obj.write(data)
else:
print("-----file rece done-----")
file_obj.close()
else:
print(STATUS_CODE[response["status_code"]]) def _get(self,*args,**kwargs):
'''下载文件命令'''
data = args[0]
if data.get('filename') is None:
self.send_response(255)
user_home_dir = "%s\%s" %(settings.USER_HOME,self.user["Username"])
file_abs_path = "%s\%s" %(user_home_dir,data.get('filename'))
print("file abs path",file_abs_path) if os.path.isfile(file_abs_path):
file_obj = open(file_abs_path,'rb')
file_size = os.path.getsize(file_abs_path)
self.send_response(257,data = {'file_size':file_size})
self.request.recv(1) #等待客户端确认,防粘包 if data.get('md5'):
md5_obj = hashlib.md5()
for line in file_obj:
self.request.send(line)
md5_obj.update(line)
else:
file_obj.close()
md5_val = md5_obj.hexdigest()
self.send_response(258,{'md5':md5_val})
print("send file done...")
else:
for line in file_obj:
self.request.send(line)
else:
file_obj.close()
print("send file done...")
else:
self.send_response(256) def _ls(self,*args,**kwargs):
'''显示当前目录下的所有文件'''
if os.getcwd() == '%s\\bin'% settings.BASE_DIR:
user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
self.request.send(json.dumps(os.listdir(user_home_dir)).encode())
else:self.request.send(json.dumps(os.listdir()).encode()) def _cd(self,*args,**kwargs):
'''改变工作目录'''
data = args[0]
user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
file_abs_path = "%s\%s" %(user_home_dir,data.get('path'))
try:
os.listdir(file_abs_path)
except FileNotFoundError as e:
self.request.send(json.dumps(e).encode())
return
self.request.send(json.dumps(259).encode())
os.chdir(file_abs_path)
return file_abs_path def _breakpoint(self,*args,**kwargs):
'''断点续传'''
data = args[0]
if data.get('filename') is None:
self.send_response(255)
user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"])
file_abs_path = "%s\%s" % (user_home_dir, data.get('filename'))
print("file abs path", file_abs_path)
print(data.get('breakpoint')) if os.path.isfile(file_abs_path):
file_obj = open(file_abs_path, 'rb')
file_obj.seek(data.get('breakpoint'))
file_size = os.path.getsize(file_abs_path)
self.send_response(257, data={'file_size': file_size})
self.request.recv(1) # 等待客户端确认 if data.get('md5'):
md5_obj = hashlib.md5()
for line in file_obj:
self.request.send(line)
md5_obj.update(line)
else:
file_obj.close()
md5_val = md5_obj.hexdigest()
self.send_response(258, {'md5': md5_val})
print("send file done...")
else:
for line in file_obj:
self.request.send(line)
else:
file_obj.close()
print("send file done...")
else:
self.send_response(256)
pass

server端

 #client端
# import socket
import hashlib
import os,json
import optparse
import socketserver STATUS_CODE = {
250 : "Invalid cmd format,e.g:{'action':'get','filename':'test.py','size':344",
251 : "Invalid cmd",
252 : "Invalid auth data",
253 : "Wrong username or password..",
254 : "Passed authentication",
255 : "Filename doesn't provided",
256 : "File doesn't exist on server",
257 : "ready to send file",
258 : "md5 verification",
259 : "Directory has been switched"
} class FTPClient(object):
'''客户端'''
def __init__(self):
'''用户信息输入格式化
变量定义'''
parser = optparse.OptionParser()
parser.add_option('-s', '--server', dest='server', help ='ftp server ip_addr')
parser.add_option('-p','--port', type='int', dest='port', help='ftp server port')
parser.add_option('-U', '--username', dest='username', help='username')
parser.add_option('-P', '--Password', dest='password', help='password')
self.options, self.args = parser.parse_args()
self.verify_args(self.options,self.args)
self.make_connection() def make_connection(self):
'''连接服务器'''
self.sock = socket.socket()
self.sock.connect((self.options.server,self.options.port)) def verify_args(self,options,args):
'''校验参数合法性'''
if options.username and options.password:
pass
elif options.username is None and options.password is None:
pass
else:
if options.username is None or options.password is None:
print('Error:username and password must be provided together..')
if options.server and options.port:
if options.port > 0 and options.port < 65535:
return True
else:
exit('Err:host port must in 0-65535') def authenticate(self):
'''用户验证'''
if self.options.username:
return self.get_auth_result(self.options.username, self.options.password)
else:
retry_count = 0
while retry_count < 3:
username = input("username:").strip()
password = input("password:").strip()
return self.get_auth_result(username,password) def get_auth_result(self,user,password):
'''用户认证'''
data = {'action':'auth',
'username':user,
'password':password} self.sock.send(json.dumps(data).encode())
response = self.get_response()
if response.get('status_code') == 254:
print("Passed authentication!")
self.user = user
return True
else:
print(data.get('status_msg'))
print('response:',data) def __md5_required(self,cmd_list):
'''检测命令是否需要进行MD5验证'''
if '--md5' in cmd_list:
return True def show_progress(self,total):
'''进度条'''
received_size = 0
current_percent = 0
while received_size < total:
if int((received_size / total) * 100) > current_percent:
print(">",end='',flush=True)
current_percent = int((received_size / total) * 100)
new_size = yield
received_size += new_size def send_response(self,status_code,data=None):
'''向服务器端返回数据'''
response = {'status_code': status_code, 'status_msg':STATUS_CODE[status_code]}
if data:
response.update(data)
self.sock.send(json.dumps(response).encode()) def get_response(self):
'''得到服务器端回复结果'''
data = self.sock.recv(1024)
data = json.loads(data.decode())
return data def _get(self,cmd_list):
'''下载文件'''
print("get--",cmd_list)
if len(cmd_list) == 1:
print("no filename follows...")
return
data_header = {
'action':'get',
'filename':cmd_list[1]
}
if self.__md5_required(cmd_list):
data_header['md5'] = True self.sock.send(json.dumps(data_header).encode())
response = self.get_response()
print(response)
try:
if response["status_code"] == 257:#ready to receive
self.sock.send(b'') #send confirmation to server
base_filename = cmd_list[1].split('/')[-1]
received_size = 0
file_obj = open(base_filename,'wb')
if self.__md5_required(cmd_list):
md5_obj = hashlib.md5()
progress = self.show_progress(response['file_size']) #generator
progress.__next__()
while received_size < response['file_size']:
data = self.sock.recv(4096)
received_size += len(data)
try:
progress.send(len(data))
except StopIteration as e:
print("100%")
file_obj.write(data)
md5_obj.update(data)
else:
print("-----file rece done-----")
file_obj.close()
md5_val = md5_obj.hexdigest()
md5_from_server = self.get_response()
if md5_from_server['status_code'] == 258:
if md5_from_server['md5'] == md5_val:
print("%s 文件一致性校验成功!"% base_filename)
print(md5_val,md5_from_server) else:
progress = self.show_progress(response['file_size']) # generator
progress.__next__()
while received_size < response['file_size']:
data = self.sock.recv(4096)
received_size += len(data)
file_obj.write(data)
try:
progress.send(len(data))
except StopIteration as e:
print("100%")
else:
print("-----file rece done-----")
file_obj.close()
else:
print(STATUS_CODE[response["status_code"]])
except Exception as e:
base_file_size = os.path.getsize(base_filename)
with open('data\\breakpoint', 'wb') as br_po:
data_header['action'] = 'breakpoint'
data_header['breakpoint'] = base_file_size
br_po.write(json.dumps(data_header).encode()) def _put(self,cmd_list):
'''上传文件'''
print("put--", cmd_list)
if len(cmd_list) == 1:
print("no filename follows...")
return
data_header = {
'action': 'put',
'filename': cmd_list[1]
}
if self.__md5_required(cmd_list):
data_header['md5'] = True self.sock.send(json.dumps(data_header).encode())
if os.path.isfile(cmd_list[1]):
file_obj = open(cmd_list[1], 'rb')
file_size = os.path.getsize(cmd_list[1])
self.send_response(257, data={'file_size': file_size})
self.sock.recv(1) # 等待服务器端确认
if self.__md5_required(cmd_list):
md5_obj = hashlib.md5()
progress = self.show_progress(file_size) # generator
progress.__next__()
for line in file_obj:
self.sock.send(line)
try:
progress.send(len(line))
except StopIteration as e:
print("100%")
md5_obj.update(line)
else:
file_obj.close()
md5_val = md5_obj.hexdigest()
md5_from_server = self.get_response()
if md5_from_server['md5'] == md5_val:
print("%s 文件一致性校验成功!"% cmd_list[1])
self.send_response(258, {'md5': md5_val})
print("send file done...")
else:
progress = self.show_progress(file_size) # generator
progress.__next__()
for line in file_obj:
self.sock.send(line)
try:
progress.send(len(line))
except StopIteration as e:
print("100%")
else:
file_obj.close()
print("send file done...")
else:
print(256) def _ls(self,*args,**kwargs):
'''获取当前目录下的所有文件'''
print('ls'.center(30,'-'))
data_header = {
'action': 'ls',
}
self.sock.send(json.dumps(data_header).encode())
ls_val = self.sock.recv(1024)
ls_val = json.loads(ls_val.decode())
for obj in ls_val:
print(obj) def _cd(self,cmd_list):
'''改变工作目录'''
print("cd--", cmd_list)
if len(cmd_list) == 1:
cmd_list.append('')
data_header = {
'action': 'cd',
'path': cmd_list[1]
}
self.sock.send(json.dumps(data_header).encode())
server_path = self.sock.recv(1024)
server_path = json.loads(server_path.decode())
if server_path == 259 :
print("%s >" % cmd_list[1],end='') def _breakpoint(self,*args,**kwargs):
'''断点续传'''
with open('data\\breakpoint', 'rb') as br_po:
data_header = json.loads(br_po.read().decode())
br_po.close()
if data_header:
print(data_header)
self.sock.send(json.dumps(data_header).encode())
response = self.get_response()
try:
if response["status_code"] == 257: # ready to receive
self.sock.send(b'') # send confirmation to server
base_filename = data_header['filename'].split('/')[-1]
received_size = data_header['breakpoint']
file_obj = open(base_filename, 'ab')
file_obj.seek(data_header['breakpoint'])
if self.__md5_required(data_header):
md5_obj = hashlib.md5()
progress = self.show_progress(response['file_size']) # generator
progress.__next__()
while received_size < response['file_size']:
data = self.sock.recv(4096)
received_size += len(data)
try:
progress.send(len(data))
except StopIteration as e:
print("100%")
file_obj.write(data)
md5_obj.update(data)
else:
print("-----file rece done-----")
file_obj.close()
md5_val = md5_obj.hexdigest()
md5_from_server = self.get_response()
if md5_from_server['status_code'] == 258:
if md5_from_server['md5'] == md5_val:
print("%s 文件一致性校验成功!" % base_filename)
with open('data\\breakpoint', 'wb') as br_po:
br_po.write()
print(md5_val, md5_from_server) else:
progress = self.show_progress(response['file_size']) # generator
progress.__next__()
while received_size < response['file_size']:
data = self.sock.recv(4096)
received_size += len(data)
file_obj.write(data)
try:
progress.send(len(data))
except StopIteration as e:
print("100%")
else:
print("-----file rece done-----")
file_obj.close()
with open('data\\breakpoint', 'wb') as br_po:
br_po.write()
except Exception as e:
base_file_size = os.path.getsize(base_filename)
with open('data\\breakpoint', 'wb') as br_po:
data_header['breakpoint'] = base_file_size
br_po.write(json.dumps(data_header).encode())
else:print('There is no need to transfer files..') def _helps(self,*args,**kwargs):
'''帮助信息'''
helps = '''
get 文件名 #下载文件
put 文件名 #上传文件
ls #获取当前目录下的所有文件
cd #改变工作目录
breakpoint #断点续传'''
print(helps) def interactive(self):
'''根据命令分配函数'''
if self.authenticate():
print('---start interactive iwth u...(helps 帮助信息)')
while True:
choice = input("[%s]:" % self.user).strip()
if len(choice) == 0: continue
cmd_list = choice.split()
if hasattr(self, "_%s" % cmd_list[0]):
func = getattr(self, "_%s" % cmd_list[0])
func(cmd_list)
else:
print("Invalid cmd") if __name__ == '__main__':
ftp = FTPClient()
ftp.interactive()

client端

socketserver实现FTP的更多相关文章

  1. 第二十九天- socketserver模块 ftp上传

    1.socketserver模块: socketserver,它提供了服务器中心类,可简化网络服务器的开发,内部使用IO多路复用以及“多线程”和“多进程”,从而实现并发处理多个客户端请求的socket ...

  2. 29 Socketserver和 ftp

    一.Socketserver #服务端 import socketserver class KnightServer(socketserver.BaseRequestHandler): def han ...

  3. python网络编程--socketserver 和 ftp功能简单说明

    1. socketserver 我们之前写的tcp协议的socket是不是一次只能和一个客户端通信,如果用socketserver可以实现和多个客户端通信.它是在socket的基础上进行了一层封装,也 ...

  4. python socketserver 实现 ftp功能

    需求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp server上随意切换目录 允许用户查看当前目 ...

  5. python学习道路(day9note)(socketserver编程,ftp)

    1.ftp client #!/usr/bin/env python #_*_coding:utf-8_*_ import socket import subprocess user_data = { ...

  6. Python开发程序:FTP程序

    作业:开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp se ...

  7. (转)Python开发程序:支持多用户在线的FTP程序

    原文链接:http://www.itnose.net/detail/6642756.html 作业:开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ...

  8. 02: SocketServer服务

    网络编程其他篇 目录: 1.1 SocketServer四种基本流及 异步处理理论部分 1.2 创建socketserver实现: 多客户端并发 1.3 SocketServer实现多并发FTP 部分 ...

  9. Python开发【项目】:FTP程序

    作业:开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp se ...

随机推荐

  1. Django之如何预防csrf功能的方式 form提交与ajax提交

    1. 什么是csrf认证: 主要是防止别人恶意登录你的账户信息用的: 2. csrf认证在django的实现方式: 分为两种, 一种是from表单提交的方式,另一种是ajax提交实现方式 前端: &l ...

  2. 关于游览器 cookie的操作类

    var Cookie = { getCookie : function(c_name,is){ var value = this._getCookie(c_name); if(JSON &&a ...

  3. 使用jQuery+huandlebars循环遍历中使用索引

    兼容ie8(很实用,复制过来,仅供技术参考,更详细内容请看源地址:http://www.cnblogs.com/iyangyuan/archive/2013/12/12/3471227.html) & ...

  4. 关于http以及aphace配置https

    我是通过腾讯云配置的ssl.   网站:www.xian029.cn 免费申请,然后通过phpstudy  来配置的. 密码学:   研究密码编码与解码的学科,可以分为编码学和破译学.   HTTPS ...

  5. 在网站中使用UEditor富文本编辑器

    UEditor是由百度WEB前端研发部开发的所见即所得的开源富文本编辑器,具有轻量.可定制.用户体验优秀等特点. 官网链接 进入到下载页面,选择相应的版本下载 这里我们使用ASP.NET开发,所以选择 ...

  6. python 常用模块(一): os模块,序列化模块(json模块 pickle模块 )

    1.os模块 2.序列化模块:(1)json模块 和 pickle模块 一.os模块 os.path.abspath: (1)把路径中不符合规范的/改成操作系统默认的格式 import os path ...

  7. Django-ConttentType

    一 content-type 在django中,有一个记录了项目中所有model元数据的表,就是ContentType,表中一条记录对应着一个存在的model,所以可以通过一个ContentType表 ...

  8. 震惊!90%的程序员不知道的Java知识!

    震惊!90%的程序员不知道的Java知识! 初学Java的时候都会接触的代码 public static void main(String[] args){ ... } 当时就像背公式一样把这行代码给 ...

  9. 服务器重新启动,oracle数据库重新连接问题

    最近服务器使用期限到了,用户无法登陆,联系了网络的同事,重新开启了服务器,用户可以重新登陆了,但是在使用oracle数据库的时候,发现报了以下的错误: 很明显是数据库服务没有启动,解决这个问题分两步: ...

  10. 代码之髓读后感——容器&并发

    容器 单个地址存放单个数据,但是如果有多个数据,而这些数据互相关联,则我们更希望的是将他们能够更好的在内存中组织在一起.于是便出现了容器的概念. 在不同的语言中,容器的名称不同,性质各异.比如,C 语 ...