Python09作业思路及源码:高级FTP服务器开发(仅供参考)

高级FTP服务器开发

一,作业要求

高级FTP服务器开发

  1. 用户加密认证(完成)
  2. 多用户同时登陆(完成)
  3. 每个用户有不同家目录且只能访问自己的家目录(完成)
  4. 对用户进行磁盘配额,不同用户配额可不同(完成)
  5. 用户登录server后,可切换目录(完成)
  6. 查看当前目录下文件(完成)
  7. 上传下载文件保持文件一致性(完成)
  8. 传输过程中实现进度条(完成)
  9. 可以创建或删除目录及文件(完成)
  10. 支持断点续传(未做)

二,程序文件清单

Python09作业思路及源码:高级FTP服务器开发(仅供参考)

  • Folder目录:用户文件目录
  • bin目录:程序启动文件目录
  • conf目录:用户配置文件目录
  • core目录:程序核心代码目录
  • log目录:程序日志文件目录

三,程序流程简图

Python09作业思路及源码:高级FTP服务器开发(仅供参考)

四,程序测试样图

  • 创建账户

Python09作业思路及源码:高级FTP服务器开发(仅供参考)

  • 用户登录

Python09作业思路及源码:高级FTP服务器开发(仅供参考)

  • 基本操作

Python09作业思路及源码:高级FTP服务器开发(仅供参考)

Python09作业思路及源码:高级FTP服务器开发(仅供参考)

Python09作业思路及源码:高级FTP服务器开发(仅供参考)

Python09作业思路及源码:高级FTP服务器开发(仅供参考)

五,核心源码清单

  • 客户端核心源码
 #!usr/bin/env python
# -*- coding:utf-8 -*-
# auther:Mr.chen
# 描述: import socket,os
import time,json DIR = os.path.dirname(os.path.abspath(__file__))
DIR = DIR.replace('core','Folder/')
HOST = 'localhost'
PORT = 8888 def ls_Method(s):
s.send("Begin!")
data = ''
while True:
buffer = s.recv(1024)
if buffer == 'Exit!':
break
if not buffer:
print ("服务器传输错误!")
return
data += buffer
print (data) def put_Method(s,action,filename):
if os.path.exists(DIR+filename) and os.path.isdir(DIR+filename) == False:
with open(DIR+filename,'r') as f:
data = f.read()
data_size = len(data)
s.send(str(data_size))
if s.recv(1024) == 'OK!':
s.send(filename)
if s.recv(1024) == 'OK!':
print ("文件开始上传,请稍后...")
with open(DIR+filename,'r') as f:
Num = None
data = ''
while True:
buffer = f.read(1024)
if not buffer:
s.send("Exit!")
break
s.send(buffer)
data += buffer
Num = download_Progress(data_size, len(data), Num)
if s.recv(1024) == 'OK!':
print ("上传成功!磁盘配额剩余{0}M".format(s.recv(1024)))
else:
print ("文件传输有损,请重新上传!")
else:
print ("不能上传!服务器上已有重名的文件")
else:
print ("磁盘配额已满,请清理磁盘空间!")
else:
s.send("False!")
print ("上传失败,没有这个文件或目标是个文件夹") def get_Method(s,action,filename):
s.send(filename)
print ("正在下载,请等待...")
data = ''
data_size = s.recv(1024)
if data_size == "Flase!":
print ("下载失败!服务器没有找到或目标是个文件夹")
return
data_size = int(data_size)
Num = None
while True:
buffer = s.recv(1024)
if not buffer :
print ("文件损坏,请重新下载!")
break
data += buffer
Num = download_Progress(data_size,len(data),Num)
if data_size == len(data):
with open(DIR + filename, 'w') as f:
f.write(data)
print ("下载成功!")
break def cd_Method(s,action,filename):
s.send(filename)
re = s.recv(1024)
if re == 'OK!':
print ("命令执行成功!")
elif re == 'NULL!':
print ("已到根目录,不能继续返回!")
else:
print ("目录没有找到!") def mkdir_Method(s,action,filename):
s.send(filename)
if s.recv(1024) == 'OK!':
print ("目录创建成功!")
else:
print ("已有同名目录或文件!") def rm_Method(s,action,filename):
s.send(filename)
re = s.recv(1024)
if re == "OK!":
print ("删除成功!磁盘配额剩余{0}M".format(s.recv(1024)))
elif re == "DIR!":
while True:
decide = raw_input("您选择的目标是个文件夹,是否递归删除(y/n):")
if decide == 'y':
s.send("OK!")
re = s.recv(1024)
if re == "OK!":
print ("删除成功,磁盘配额剩余{0}M".format(s.recv(1024)))
break
else:
print ("删除失败,原因未知!")
break
elif decide == 'n':
s.send("False!")
break
else:
print ("您的输入有误!")
else:
print ("没有这个文件") def download_Progress(size_total,size,Num):
num = size * 100 / size_total
if Num == None:
# print (str(num)+"%")
print "\r%d" % num,
time.sleep(0.01)
return num
elif num == Num:
return num
else:
print "\r%d" % num,
time.sleep(0.01)
return num def MD5(password):
"""
加密函数
:param password:
:return:
"""
import hashlib
return hashlib.md5(password).hexdigest() def File_transfer(s):
"""
用户指令函数
:param s:
:return:
""" while True:
command = raw_input("请输入你想执行的命令>>")
if not command:
continue
if command.lower().strip() == 'help':
text = """
请用'put'+'空格'+'文件名'的格式上传文件
请用'get'+'空格'+'文件名'的格式下载文件
请用'cd'+'空格'+'目录名'的格式进入家目录下的子文件夹
请用'cd'+'空格'+'..'的格式返回上级目录
请用'mkdir'+'空格'+'目录名'的格式进入家目录的文件夹
请用'rm'+'空格'+'文件名/目录名'的格式删除家目录下的文件
输入'ls'查看用户服务器家目录
"""
print (text)
continue
try:
action,filename = command.strip().split()
action = action.lower()
except:
if command.lower().strip() == 'ls':
s.send('ls')
print ("正在查询,请稍后...")
if s.recv(1024) == 'OK!':
ls_Method(s)
else:
print ("您的输入有误!输入help查看帮助文档")
continue
else:
s.send(action)
if s.recv(1024) == 'OK!':
eval(action+'_Method')(s,action,filename)
else:
print ("您的输入有误!输入help查看帮助文档") def Login(s):
"""
用户登录
:param s:
:return:
"""
while True:
name = raw_input("请输入你的登陆名:").strip()
password = raw_input("请输入你的密码:").strip()
if not name or not password:
print ("用户名和密码不能为空!")
continue
password = MD5(password) #密码加密
data = [name,password]
s.send(json.dumps(data))
if s.recv(1024) == 'OK!':
print ("用户登陆成功!")
File_transfer(s)
else:
print ("用户登陆失败!") def Main():
"""
用户登陆
:param s:
:param log:
:return:
"""
s = socket.socket()
try:
s.connect((HOST, PORT))
s.send("Ready!") data = s.recv(1024) #接收服务器欢迎信息
if not data:
print ("服务器异常!")
else:
print (data)
Login(s)
except Exception,e:
print "服务器连接不上....", e
finally:
s.close() if __name__ == "__main__":
Main()
  • 服务器端核心源码
 #!usr/bin/env python
# -*- coding:utf-8 -*-
# auther:Mr.chen
# 描述: import SocketServer
import os,time,sys,json
import admin_configure
DIR = os.path.dirname(os.path.abspath(__file__))
DIR = DIR.replace('core','Folder/') class Myserver(SocketServer.BaseRequestHandler): def __init__(self,request,client_address,server):
SocketServer.BaseRequestHandler.__init__(self,request,client_address,server)
self.Name = '' #用户名
self.Password = '' #用户密码
self.Quota = '' #用户磁盘配额
self.Home_path = '' #用户家目录路径
self.Current_path = '' #用户当前路径
self.DIR = [] #用户进入过的子目录列表 def ls_Method(self):
data = self.request.recv(1024)
if data == 'Begin!':
data = os.popen('ls'+' '+self.Current_path).read()
self.request.sendall(data)
time.sleep(0.5)
self.request.send("Exit!") def put_Method(self):
data_size = self.request.recv(1024)
if data_size == 'False!':
return
if int(self.Quota) >= int(data_size):
self.request.send("OK!")
filename = self.request.recv(1024)
if os.path.exists(self.Current_path+filename) == False:
self.request.send("OK!")
data = ''
while True:
buffer = self.request.recv(1024)
if buffer == 'Exit!':
break
if not buffer:
break
data += buffer
self.Quota = str(int(self.Quota) - len(data))
dict = admin_configure.config_read(self.Name)
dict['Quota'] = self.Quota
admin_configure.config_write(dict)
with open(self.Current_path+filename,'w') as f:
f.write(data)
if len(data) == int(data_size):
self.request.send("OK!")
time.sleep(0.25)
Quota = str(float(self.Quota)/1000000)
self.request.send(Quota)
else:
self.request.send("Flase!")
else:
self.request.send("False!")
else:
self.request.send("Flase!") def get_Method(self):
filename = self.request.recv(1024)
if os.path.exists(self.Current_path+filename) and os.path.isdir(self.Current_path+filename) == False:
with open(self.Current_path+filename,'r') as f:
data = f.read()
self.request.send(str(len(data)))
time.sleep(0.5)
self.request.sendall(data)
else:
self.request.send("Flase!") def cd_Method(self):
filename = self.request.recv(1024)
if filename == '..':
if len(self.DIR) == 0:
self.request.send("NULL!")
return
else:
# self.Current_path = self.Current_path.replace('/'+self.DIR[0]+'/','/')
list = self.Current_path.split('/')
del list[0]
del list[len(list) - 1]
del list[len(list) - 1]
str = '/'
for i in range(len(list)):
str = str + list[i] + '/'
self.Current_path = str
del self.DIR[0]
self.request.send("OK!")
elif os.path.isdir(self.Current_path+filename):
self.Current_path = self.Current_path + filename + '/'
self.DIR.insert(0,filename)
self.request.send("OK!")
else:
self.request.send("False!") def mkdir_Method(self):
filename = self.request.recv(1024)
if os.path.exists(self.Current_path+filename):
self.request.send("False!")
else:
os.system("mkdir -p " + self.Current_path + filename)
if os.path.exists(self.Current_path + filename):
self.request.send("OK!")
else:
self.request.send("False!") def rm_Method(self):
filename = self.request.recv(1024)
if os.path.exists(self.Current_path+filename):
if os.path.isdir(self.Current_path+filename):
self.request.send("DIR!")
if self.request.recv(1024) == "OK!":
data = os.popen('du'+' '+ '-sk' + ' ' + self.Current_path+filename).read()
data_size,file = data.strip().split()
os.system("rm -rf " + self.Current_path + filename)
self.Quota = str(int(self.Quota) + int(data_size))
dict = admin_configure.config_read(self.Name)
dict['Quota'] = self.Quota
admin_configure.config_write(dict)
self.request.send("OK!")
time.sleep(0.25)
Quota = str(float(self.Quota) / 1000000)
self.request.send(Quota) else:
return
else:
with open(self.Current_path+filename,'r') as f:
data = f.read()
os.system("rm -f " + self.Current_path + filename)
self.Quota = str(int(self.Quota) + len(data))
dict = admin_configure.config_read(self.Name)
dict['Quota'] = self.Quota
admin_configure.config_write(dict)
self.request.send("OK!")
time.sleep(0.25)
Quota = str(float(self.Quota) / 1000000)
self.request.send(Quota)
else:
self.request.send("False!") def Login_Method(self,data):
re = admin_configure.config_read(data[0])
if re == None:
return False
else:
if re['Password'] == data[1]:
self.Name = re['Name']
self.Password = re['Password']
self.Quota = re['Quota']
self.Home_path = re['Home_path']
self.Current_path = re['Current_path']
self.DIR = []
return True
else:
return False def handle(self):
conn = self.request
conn.recv(1024)
print ("收到来自{0}的客户端连接...".format(self.client_address[0]))
conn.send("欢迎你!")
try:
while True:
print ("正在等待客户端发送验证信息!")
self.data = json.loads(conn.recv(1024))
# if not self.data:
# break
if not self.data or type(self.data) != list:
conn.send("false!")
else:
re = self.Login_Method(self.data)
if re == True:
print ("客户端认证成功!")
conn.send("OK!")
while True:
print ("正在等待客户端响应...")
data = conn.recv(1024)
# if not data:
# break
if hasattr(self,data +'_Method'):
conn.send("OK!")
getattr(self,data +'_Method')()
else:
conn.send("flase") else:
conn.send("flase!")
except Exception,e:
print "客户端失去连接!",e def Main():
HOST = 'localhost'
PORT = 8888
s = SocketServer.ThreadingTCPServer((HOST, PORT), Myserver)
print ("正在等待客户端连接...")
s.serve_forever() if __name__ == "__main__":
Main()
上一篇:解决Kali Linux没有声音


下一篇:C#中委托、事件和回调函数的理解