socketserver+socket实现较为复杂的ftp,支持多用户在线
客户端(ftp_client.py)
import socketserver,json,hashlib,os
from pymongo import MongoClient '''
*****要点*****
1.面向对象编程
2.反射的利用
3.代码的高度解耦
4.md5加密传输认证
5.数据库查询验证
**************
'''
db = MongoClient('localhost', 27017)
curent_document = ''
#此类用于处理一系列客户端请求
class deal():
def __init__(self,name):
self.name = name #用户登录认证
def deal_login(self,data,client):
global logined_uname,db
BASE_DIR = ''#基目录
#选择数据库
d = db['DB_FOR_PYTHON']
#选择集合
users = d['FTP_USERS']
name = data['name']
pwd = data['pwd']
u = users.find_one({'name':name ,'pwd':pwd})
#用户不存在,返回0
if u == None or u == '':
#使用find()和find_one返回的结果分别是cursor和一条记录
u1 = users.find_one({'name':name})
if u1 == None or u1 == '':
#无此用户
client.send(b'')
return ''.encode()
else:
#密码有误
client.send(b'')
return ''.encode()
else:
#登录成功
client.send(b'')
logined_uname = name
return ''.encode() #上传处理
def deal_upload(self,data,request):
#查出用户的磁盘配额大小,并检查用户上传文件大小,和要上传的文件加以对比,看是否可以继续上传
user1 = db.DB_FOR_PYTHON.FTP_USERS.find_one({'name':logined_uname})
#用户的磁盘配额大小
space_limite = user1['space']
print('当前用户磁盘总空间:{}'.format(str(space_limite)))
name = data['name']
#上传文件大小
totalsize = data['size']*1024
m = hashlib.md5()
request.send('ok'.encode())
cur_size = 0
cur_content =b''
size = 0
global BASE_DIR
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
file_name = ''
#剩余磁盘大小
space = 0
u_dir = BASE_DIR+os.sep+'USERS_HOME'+os.sep+logined_uname.upper()+"_HOME"
if os.path.exists(u_dir):
# 用户总目录文件夹大小(bit计算)
real_space = (os.stat(u_dir).st_size)*1024
space = space_limite - real_space
file_name = u_dir+os.sep+name
else:
os.mkdir(u_dir)
space = space_limite
file_name = u_dir + os.sep + name
#如果上传资源的大小小于等于磁盘剩余空间,则继续
if space >= totalsize:
print('可以发送')
f = open(file_name,'wb')
while cur_size < totalsize:
if totalsize - cur_size >1024*1024:
size = 1024*1024
else:
size = totalsize - cur_size
print(size)
data = request.recv(size)
m.update(data)
cur_content += data
f.write(data)
cur_size += len(data)*1024
else:
print('haha')
f.close()
request.send(json.dumps({'state':'upload success!','md5':m.hexdigest()}).encode())
return json.dumps({'state':'upload success!','md5':m.hexdigest()}).encode()
else:
request.send(json.dumps({'state':'upload fail,your filesize exceeding the rest of your own space!','rest':space,'filesize':totalsize,'md5':None}).encode())
return json.dumps({'state':'upload fail,your filesize exceeding the rest of your own space!','rest':space,'filesize':totalsize,'md5':None}).encode()
#下载实现
def deal_download(self,data):
self.data = data['name']
return self.data
#用户切换目录
def deal_cd(self,data):
global BASE_DIR,curent_document
#当前用户基目录
ROOT_DOC = BASE_DIR+os.sep+'USERS_HOME'+os.sep+logined_uname.upper()+"_HOME"
current_document = ROOT_DOC
#用户输入的目录
manual_enter = data['cd_document']
current_document = os.chdir(manual_enter) if os.path.exists(manual_enter) else curent_document
print("用户要跳转的目录:",current_document)
pass
#查看文件
def deal_dir(self):
pass
#断点续传功能
def deal_cont(self):
pass
#面向对象的方式实现
class ftp_server(socketserver.BaseRequestHandler):
def handle(self):
logined_uname = ''
while True:
try:
#接收来自客户端的信息
data = self.request.recv(1024).decode()
data = json.loads(data)
print(data)
cmd = data['req']
#创建服务端对象
d = deal('ser')
if hasattr(d,cmd):
c = getattr(d,cmd)
res = c(data,self.request).decode()
print(res)
except ConnectionResetError as e:
print('error:',e)
break #主方法入口
if __name__ == '__main__':
HOST,PORT = 'localhost',9999
server = socketserver.ThreadingTCPServer((HOST,PORT),ftp_server)
server.serve_forever()
服务端(ftp_server.py)
# coding = utf-8 import socket,json,re,os,hashlib
login_uname = ''
class client_do(object):
def __init__(self,name):
self.name = name
#登录
def deal_login(self,data,client):
try:
global login_uname
global state
name = data.split()[1].split('\\')[0]
pwd = data.split()[1].split('\\')[1]
req = data.split()[0]
data = {
'req':req,
'name':name,
'pwd':pwd
}
client.send(json.dumps(data).encode())
response = client.recv(1024).decode()
if response == '':
login_uname = name
global lg_s
lg_s = '\033[32;1m $' + login_uname + '>>:\033[0m'
state = response
#返回结果可能为0(无此用户),1(验证成功),2(密码有误)
return response
except Exception as e:
print("登录出错:",e)
#上传
def deal_upload(self,mes,client):
try:
if state == '':
filename = mes.split()[1]
if os.path.isfile(filename):
f = open(filename, 'rb')
filesize = os.stat(filename).st_size
print('filesize:', filesize)
data = {
'req': mes.split()[0],
'name': filename,
'size': filesize,
'overwrite': True
}
client.send(json.dumps(data).encode())
# 接受服务器返回的信息,防止粘包,同时得到磁盘是否够传信息
res = client.recv(1024)
print('first response:', res.decode())
# 准备发送信息
m = hashlib.md5()
for line in f:
client.send(line)
m.update(line)
md5_client = m.hexdigest()
f.close()
# 接受服务器请求处理结果
response_info = client.recv(1024).decode()
response_info = json.loads(response_info)
md5_server = response_info['md5']
print('md5_client:{},\t md5_server:{}'.format(md5_client, md5_server))
print("状态:{}".format(response_info['state']))
#上传ok
return ''
else:
#上传出错
return ''
else:
print('请先完成登录')
except Exception as e:
print('上传出错:',e)
#用户切换目录
def deal_cd(self):
pass
#查看文件
def deal_dir(self):
pass
#断点续传功能
def deal_cont(self):
pass
client = socket.socket()
client.connect(('localhost',9999))
state = 0
lg_s =">>:"
while True:
mes = input(lg_s)
if mes == '' or mes ==None:continue
cl_req = mes.split()[0]
c = client_do('client')
if hasattr(c,cl_req):
s = getattr(c,cl_req)
res = s(mes,client)
else:
print('无效的命令')
说明:
代码实现的功能有用户登录认证,上传的前提是要登录,文件上传,用户磁盘配额,断点续传和目录跳转功能暂未实现。后续实现补上
运行截图:
1.数据库截图:
2.客户端截图:
3.服务端截图:
socketserver+socket实现较为复杂的ftp,支持多用户在线的更多相关文章
- python 开发一个支持多用户在线的FTP
### 作者介绍:* author:lzl### 博客地址:* http://www.cnblogs.com/lianzhilei/p/5813986.html### 功能实现 作业:开发一个支持多用 ...
- Python3学习之路~8.6 开发一个支持多用户在线的FTP程序-代码实现
作业: 开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp s ...
- (转)Python开发程序:支持多用户在线的FTP程序
原文链接:http://www.itnose.net/detail/6642756.html 作业:开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ...
- 老男孩python作业7-开发一个支持多用户在线的FTP程序
作业6:开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp s ...
- python之FTP程序(支持多用户在线)
转发注明出处:http://www.cnblogs.com/0zcl/p/6259128.html 一.需求 1. 用户加密认证 (完成)2. 允许同时多用户登录 (完成)3. 每个用户有自己的家目录 ...
- 实现支持多用户在线的FTP程序(C/S)
1. 需求 1. 用户加密认证 2. 允许多用户登录 3. 每个用户都有自己的家目录,且只能访问自己的家目录 4. 对用户进行磁盘分配,每一个用户的可用空间可以自己设置 5. 允许用户在ftp ser ...
- 开发一个支持多用户在线的FTP程序
要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp server上随意切换目录 允许用户查看当前目 ...
- CentOS随笔 - 2.CentOS7安装ftp支持(vsftpd)
前言 转帖请注明出处: http://www.cnblogs.com/Troy-Lv5/ 在前一篇文章中介绍了在虚拟机中安装CentOS7, 接下来就要进行配置了, 第一个就是安装ftp支持. 要不然 ...
- 多用户在线FTP程序
项目名:多用户在线FTP程序 一.需求 1.用户加密认证 2.允许同时多用户登录 3.每个用户有自己的家目录 ,且只能访问自己的家目录 4.对用户进行磁盘配额,每个用户的可用空间不同 5.允许用户在f ...
随机推荐
- [IR课程笔记]Page Rank
主要目的: 在网络信息检索中,对每个文档的重要性作出评价. Basic Idea: 如果有许多网页链接到某一个网页,那么这个网页比较重要. 如果某个网页被一个权重较大的网页链接,那么这个网页比较重要. ...
- zkdash部署
1.拉取代码 #git clone https://github.com/ireaderlab/zkdash.git 2.安装依赖包 #cd zkdash #yum install -y python ...
- c# 容器类简介
c# 容器类简介 C# 中主要有两类容器:一个是 System.Array 类(参阅:http://msdn.microsoft.com/library/default.asp?url=/libr ...
- 使用Dubbo实现RPC调用
启动Dubbo服务有2个方式,1是通过xml配置,2是通过注解来实现,这点和Spring相似. 采用XML配置如下: <?xml version="1.0" encoding ...
- BZOJ_3786_星系探索_splay维护出栈入栈序
BZOJ_3786_星系探索_splay维护出栈入栈序 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为 ...
- js 改变对象的引用地址
在业务处理中我们经常会碰到列表中有编辑和新增按钮,为了能够提高代码的公用性,我们经常会使用同一组件处理. 这样会出现一个问题就是编辑的时候直接把对象传过去,直接赋值,引用地址是同一个,所以不管修改了那 ...
- bzoj 4559 [JLoi2016]成绩比较 —— DP+拉格朗日插值
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4559 看了看拉格朗日插值:http://www.cnblogs.com/ECJTUACM-8 ...
- spring boot 部署 发布
Spring Boot应用的打包和部署 字数639 阅读2308 评论0 喜欢5 现在的IT开发,DevOps渐渐获得技术管理人员支持.云计算从ECS转向Docker容器技术.微服务的概念和讨论也越来 ...
- web应用目录结构
news web(应用的名字)||--静态资源和JSP文件都可以直接放在web应用的目录下,浏览器可以直接访问(html/jsp/css)|--WEB-INF 可以没有,但是最好有,一旦有,则结构需要 ...
- 关于group_concat函数拼接字符超长的问题
昨天测试的人火急火燎的找我,跟我说数据不对!说明情况后我去查看,原来是数据上有个子查询出来的字段没有完全展示 问题很明显,就是数据被截断了.下面贴上我写的查询 wyids_是正确的显示,通过它子查询出 ...