高级FTP服务器开发

一,作业要求

高级FTP服务器开发

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

二,程序文件清单

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

三,程序流程简图

四,程序测试样图

  • 创建账户

  • 用户登录

  • 基本操作

五,核心源码清单

  • 客户端核心源码
 #!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()

Python09作业思路及源码:高级FTP服务器开发(仅供参考)的更多相关文章

  1. 从零开始学Python07作业源码:虚拟人生(仅供参考)

    bin目录: Simulated_life_start.py #!usr/bin/env python # -*- coding:utf-8 -*- # auther:Mr.chen # 描述: im ...

  2. python10作业思路及源码:类Fabric主机管理程序开发(仅供参考)

    类Fabric主机管理程序开发 一,作业要求 1, 运行程序列出主机组或者主机列表(已完成) 2,选择指定主机或主机组(已完成) 3,选择主机或主机组传送文件(上传/下载)(已完成) 4,充分使用多线 ...

  3. 高级FTP服务器开发

    要求: 1. 用户加密认证 2. 多用户同时登陆 3. 每个用户有自己的家目录且只能访问自己的家目录 4. 对用户进行磁盘配额.不同用户配额可不同 5. 用户可以登陆server后,可切换目录 6. ...

  4. Unity上一页下一页切换功能实现源码(仅供参考)

    在做项目时我们有时需要实现切换上一页下一页图片,切换上一首下一首歌曲等等类似的功能.这里写了个简单的实现源码(仅供参考),要是有更好的方法欢迎提出来,共同进步~ 以切换上一页下一页图片为例: usin ...

  5. pdb 源码索引符号服务器创建过程

    pdb是调试程序必不可少的东西,它保存着一个exe或dll的调试信息,对pdb进行源码索引可以快速找到软件对应该版本的代码,本文以subversion版本控制服务器进行介绍 一.需要安装的软件 win ...

  6. YYCache设计思路及源码学习

    设计思路 利用YYCache来进行操作,实质操作分为了内存缓存操作(YYMemoryCache)和硬盘缓存操作(YYDiskCache).内存缓存设计一般是在内存中开辟一个空间用以保存请求的数据(一般 ...

  7. 史上最详细的IDEA优雅整合Maven+SSM框架(详细思路+附带源码)

    目录 前言: 1. 搭建整合环境 2.Spring框架代码的编写 3.SpringMVC框架代码的编写 4. Spring整合SpringMVC的框架 5.MyBatis框架代码的编写 6. Spri ...

  8. asp.net abp模块化开发之通用树2:设计思路及源码解析

    一.前言 上一篇大概说了下abp通用树形模块如何使用,本篇主要分析下设计思路. 日常开发中会用到很多树状结构的数据,比如:产品的多级分类.省市区县,大多数系统也会用到类似“通用字典/数据字典”的功能, ...

  9. 分享一个客户端程序(winform)自动升级程序,思路+说明+源码

    做winform的程序,不管用没用过自动更新,至少都想过自动更新是怎么实现的. 我这里共享一个自动更新的一套版本,给还没下手开始写的人一些帮助,也希望有大神来到,给指点优化意见. 本初我是通过sock ...

随机推荐

  1. 去IOE的一点反对意见以及其他

    某天在机场听见两老板在聊天,说到他们目前销售的报表老跟不上的问题,说要请一个人,专门合并和分析一些发过来的excel表格,我真想冲上去说,老板,你需要的是一个信息处理的系统,你需要咨询么.回来一直耿耿 ...

  2. “此网页上的某个 Web 部件或 Web 表单控件无法显示或导入。找不到该类型,或该类型未注册为安全类型。”

    自从vs装了Resharper,看见提示总是手贱的想去改掉它.于是乎手一抖,把一个 可视web部件的命名空间给改了. 喏,从LibrarySharePoint.WebPart.LibraryAddEd ...

  3. BPM协同平台解决方案分享

    一.需求分析 企业信息化的过程都是从单纯解决一个业务功能问题,到解决企业内部业务流程问题,再扩展到解决不同业务流程的关联互动问题, 核心是业务的集成和业务的协同,需要有一个统一的业务协同平台. 国内的 ...

  4. Visual Studio 2013 添加一般应用程序(.ashx)文件到SharePoint项目

    默认,在用vs2013开发SharePoint项目时,vs没有提供一般应用程序(.ashx)的项目模板,本文解决此问题. 以管理员身份启动vs2013,创建一个"SharePoint 201 ...

  5. [学习笔记]JavaScript之函数式编程

    欢迎指导与讨论:) 前言 函数式编程能使我们的代码结构变得简洁,让代码更接近于自然语言,易于理解. 一.减少不必要的函数嵌套代码 (1)当存在函数嵌套时,若内层函数的参数与外层函数的参数一致时,可以这 ...

  6. Enterprise Integration Pattern - 组成简介

    近些年来,越来越多的Web应用正在逐渐向大型化的方向发展.它们通常都会包含一系列相互协作的子服务.在开发过程中,如何让这些子服务协同工作常常是软件开发人员所最为头疼的问题,如各个子服务之间的数据表示不 ...

  7. SQL Server数据库损坏、检测以及简单的修复办法

    简介     在一个理想的世界中,不会存在任何数据库的损坏,就像我们不会将一些严重意外情况列入我们生活中的日常一样,而一旦这类事情发生,一定会对我们的生活造成非常显著的影响,在SQL Server中也 ...

  8. 【初学者指南】在ASP.NET MVC 5中创建GridView

    介绍 在这篇文章中,我们将会学习如何在 ASP.NET MVC 中创建一个 gridview,就像 ASP.NET Web 表单中的 gridview 一样.服务器端和客户端有许多可用的第三方库,这些 ...

  9. ABP(现代ASP.NET样板开发框架)系列之18、ABP应用层——权限验证

    点这里进入ABP系列文章总目录 ABP(现代ASP.NET样板开发框架)系列之18.ABP应用层——权限验证 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目 ...

  10. ABP(现代ASP.NET样板开发框架)系列之22、ABP展现层——导航栏设置

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之22.ABP展现层——导航栏设置 ABP是“ASP.NET Boilerplate Project (ASP.NE ...