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 ...
随机推荐
- 04-树4 是否同一棵二叉搜索树(25 point(s)) 【Tree】
04-树4 是否同一棵二叉搜索树(25 point(s)) 给定一个插入序列就可以唯一确定一棵二叉搜索树.然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到.例如分别按照序列{2, 1, 3}和 ...
- spring cloud - 注册中心
服务注册与发现 这里我们会用到Spring Cloud Netflix,该项目是Spring Cloud的子项目之一,主要内容是对Netflix公司一系列开源产品的包装,它为Spring Boot应用 ...
- [CPP - STL] functor刨根问底儿
作为STL六大组件之一,在STL源代码及其应用中,很多地方使用了仿函数(functor),尤其在关联型容器(如set.map)以及algorithm(如find_if.count_if等)中.虽然已经 ...
- android4.3 蓝牙BLE编程
一.蓝牙4.0简介 蓝牙4.0标准包含两个蓝牙标准,准确的说,是一个双模的标准,它包含传统蓝牙部分(也有称之为经典蓝牙Classic Bluetooth)和低功耗蓝牙部分(Bluetooth Low ...
- 一个测试基础面试题——如何测试web银行开户
之前面试被问到过这样一个问题,自己答的都是一些UI界面上的case,看了一些大神的关于这类面试题的总结才知道自己差的不是一点半点,今天也总结下. 内管银行开户,有账号.用户名.用户证件类型.证件号三个 ...
- 理解HTML解析过程
浏览器解析html的过程是:接受网络数据->将二进制码变成字符->将字符变为unicode code points.->tokenizer ->tree constructor ...
- servlet与jsp理论知识讲解
servlet是java服务器端编程,是运行在服务器上的.不同于以前的java小程序. ...
- 万亿级日志与行为数据存储查询技术剖析——Hbase系预聚合方案、Dremel系parquet列存储、预聚合系、Lucene系
转自:http://www.infoq.com/cn/articles/trillion-log-and-data-storage-query-techniques?utm_source=infoq& ...
- Opencv— — image offset
// define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLUDED #include < ...
- [调试AvantCourier的笔记]
1.manifest里不能设置target sdk 不然会出现stale error. 2.manifest里要有Internet权限 3