服务器利用 socketserver 模块 构造, 实现了 多进程.

客户端仍然利用的是底层的 socket模块. 只不过进行了更深度的 解耦, 新加或者删除 某些功能 更方便

在上一个版本的基础上,增加了 新建文件夹的功能, 并且将vip用户的名字加上了颜色, 变成了黄金 vip.

服务器端设置了两个文件, 1, info( 存储用户密码); 2, vipinfo (存储所有的vip用户的名字)

还需要再补充一个log文件夹,里面用来保存所有客户的访问记录. ps: 此功能还没添加.

下面是代码:

服务器端:

 import socketserver
import struct
import pickle
import os class Myserver(socketserver.BaseRequestHandler):
def __init__(self, request, client_address, server):
self.dic_cho = {
'login': self.login, # 登录
'register': self.register, # 注册
'new_file': self.new_file, # 创建新的文件夹
'down_dir': self.down_dir, # 进入下一层
'up_dir': self.up_dir, # 进入上一层
'upload': self.upload, # 上传
'download': self.download, # 下载
'vip': self.vip, # 升级vip
'end': self.end, # 结束
'size': 102400
}
self.flag = False
self.flag_end = True
super().__init__(request, client_address, server) def my_reve(self): # 因为每次接收后的内容都会转成字典, 所以重写了接收的函数
return pickle.loads(self.request.recv(struct.unpack('i', self.request.recv(4))[0])) def my_send(self, dic): # 重写了 发送方法.
dic_pic = pickle.dumps(dic)
return self.request.send(struct.pack('i', len(dic_pic)) + dic_pic) def isvip(self, server_dict, client_dic):
"""此函数是 login函数的附属函数, 只是用来判断该用户是否为Vip :param server_dict: 服务器需要发送的字典
:param client_dic: 服务器接收的客户端发来的字典
:return: None
"""
with open('vipinfo', encoding='utf-8') as f:
for name in f:
if client_dic['username'] == name.strip():
self.flag = True
server_dict['return'] = '登录成功, 欢迎尊敬的VIP用户:\033[1;33;m%s\033[0m 访问ftp' % client_dic['username']
self.dic_cho['size'] = 10240000
server_dict['size'] = '容量:(单位:字节)%s/10240000' % os.path.getsize(self.dir_path)
return def login(self, client_dic, server_dict):
self.dir_path = os.path.join(os.path.dirname(__file__), client_dic['username'])
# 第一步 判断用户名+密码 是否正确
with open('info', encoding='utf-8') as f:
for line in f:
if client_dic['username'] + '\t' + client_dic['password'] == line.strip():
server_dict['return'] = '登录成功, 欢迎%s 用户访问ftp' % client_dic['username']
server_dict['size'] = f'容量:(单位:字节){os.path.getsize(self.dir_path)}/102400'
server_dict['dir_list'] = os.listdir(self.dir_path)
# 第二步 判断此人是不是会员, 有没有vip文件中
self.isvip(server_dict, client_dic)
# 第三步, 将字典发送给 客户端并且 结束函数
self.my_send(server_dict)
return
server_dict['return'] = '错误:输入错误'
self.my_send(server_dict) def register(self, client_dic, server_dict):
self.dir_path = os.path.join(os.path.dirname(__file__), client_dic['username'])
with open('info', encoding='utf-8') as f:
for line in f:
username, password = line.strip().split('\t')
if client_dic['username'] == username:
server_dict['return'] = '错误:用户名已存在'
self.my_send(server_dict)
return
with open('info', 'a+', encoding='utf-8') as f:
f.write(client_dic['username'] + '\t' + client_dic['password'] + '\n')
self.flag = True
server_dict['return'] = '注册成功,自动登录中'
os.mkdir(client_dic['username'])
server_dict['dir_list'] = os.listdir(self.dir_path)
server_dict['size'] = f'容量:(单位:字节){os.path.getsize(self.dir_path)}/102400'
self.my_send(server_dict) def new_file(self, client_dic, server_dict):
"""
此函数和下面的六个函数 被执行的前提是客户已经登录成功了,
且已经在客户端显示出来了文件列表, 若没有登录, 该用户访问不到此方法 此函数的功能是 在当前工作列表中新建文件夹
:param client_dic:
:param server_dict:
:return:
"""
new_name = client_dic['new_dir_name']
os.mkdir(os.path.join(self.dir_path, new_name))
server_dict['return'] = '%s 文件夹新建成功' % new_name
self.my_send(server_dict) def down_dir(self, client_dic, server_dict):
down_dir_name = client_dic['down_dir_name']
self.dir_path = os.path.join(self.dir_path, down_dir_name)
server_dict['dir_list'] = os.listdir(self.dir_path)
self.my_send(server_dict) def up_dir(self, client_dic, server_dict):
dir_path_if = os.path.dirname(self.dir_path)
if dir_path_if == os.path.dirname(__file__):
server_dict['return'] = '已经是最上层目录了'
else:
self.dir_path = dir_path_if
server_dict['dir_list'] = os.listdir(self.dir_path)
self.my_send(server_dict) def upload(self, client_dic, server_dict):
filesize = client_dic['upload_file_size']
size = os.path.getsize(self.dir_path)
if filesize+size >= self.dic_cho['size']:
server_dict['return'] = '内存不足'
self.my_send(server_dict)
return
filename = os.path.join(self.dir_path, client_dic['upload_file_name'])
with open(filename, 'wb') as f:
while filesize:
if filesize < 1024:
content = self.request.recv(filesize)
else:
content = self.request.recv(1024)
f.write(content)
filesize -= len(content)
server_dict['return'] = '上传成功'
server_dict['dir_list'] = os.listdir(self.dir_path)
self.my_send(server_dict) def download(self, client_dic, server_dict):
filename = os.path.join(self.dir_path, client_dic['download_file_name'])
filesize = os.path.getsize(filename)
server_dict['file_size'] = filesize
self.my_send(server_dict)
with open(filename, 'rb') as f:
while filesize:
if filesize > 1024:
content = f.read(filesize)
else:
content = f.read(1024)
self.request.send(content)
filesize -= len(content)
ok = self.request.recv(2)
print(ok)
self.request.send(b'download ok') if ok == b'ok' else self.request.send(b'download no') def vip(self, client_dic, server_dict):
with open('vipinfo', 'r+', encoding='utf-8') as f:
for line in f:
if client_dic['username'] == line.strip():
server_dict['return'] = '您已经是尊敬的Vip用户了'
self.my_send(server_dict)
return
f.seek(0, 2)
f.write(client_dic['username'] + '\n')
self.isvip(server_dict, client_dic)
self.my_send(server_dict) def end(self, client_dic, server_dict):
self.flag_end = False
server_dict['return'] = '程序结束'
self.my_send(server_dict) def handle(self):
server_dict = {}
flag = self.flag_end
while flag:
try:
client_dic = self.my_reve()
self.dic_cho[client_dic['opt']](client_dic, server_dict)
except Exception:pass server = socketserver.TCPServer(('127.0.0.1', 9090), Myserver)
server.serve_forever()

客户端:

 import os
import socket
import struct
import pickle
import hashlib class Myclient(socket.socket):
def __init__(self):
super().__init__()
self.dic_cho = {
'login': self.login, # 登录
'regis': self.register, # 注册
'new_file': self.new_file, # 创建新的文件夹
'down_dir': self.down_dir, # 进入下一层
'up_dir': self.up_dir, # 进入上一层
'upload': self.upload, # 上传
'download': self.download, # 下载
'vip': self.vip, # 升级vip
'end': self.end, # 结束
}
self.flag = True def my_reve(self):
return pickle.loads(self.sk.recv(struct.unpack('i', self.sk.recv(4))[0])) def my_send(self, dic):
dic_pic = pickle.dumps(dic)
return self.sk.send(struct.pack('i', len(dic_pic)) + dic_pic) def login(self):pass def register(self):pass def my_md5(self, user, pwd):
md5_obj = hashlib.md5(user.encode('utf-8'))
md5_obj.update(pwd.encode('utf-8'))
return md5_obj.hexdigest() def new_file(self):
new_file_name = input('>>>请输入新建文件夹的名字:').strip()
self.client_dict['new_dir_name'] = new_file_name
self.my_send(self.client_dict)
server_dict = self.my_reve()
print(server_dict['dir_list']) def down_dir(self):
down_dir_name = input('>>>请输入下一级文件夹的名字:').strip()
self.client_dict['down_dir_name'] = down_dir_name
self.my_send(self.client_dict)
server_dict = self.my_reve()
print(server_dict['dir_list']) def up_dir(self):
self.my_send(self.client_dict)
server_dict = self.my_reve()
print(server_dict['dir_list']) def upload(self):
upload_file_path = input('>>>请输入上传文件绝对路径:').strip()
self.client_dict['upload_file_name'] = os.path.basename(upload_file_path)
self.client_dict['upload_file_size'] = os.path.getsize(upload_file_path)
filesize = self.client_dict['upload_file_size']
self.my_send(self.client_dict)
with open(upload_file_path, 'rb') as f:
while filesize:
if filesize > 1024:
content = f.read(filesize)
else:
content = f.read(1024)
self.sk.send(content)
filesize -= len(content)
server_dict = self.my_reve()
print(server_dict['return'])
print(server_dict['dir_list']) def download(self):
download_file_name = input('>>>请输入您要下载的文件的名字:').strip()
download_file_path = input('>>>请输入要下载到本地的绝对路径以及对该文件命名:').strip()
self.client_dict['download_file_name'] = download_file_name
self.my_send(self.client_dict)
server_dict = self.my_reve()
filesize = server_dict['file_size']
with open(download_file_path, 'wb') as f:
while filesize:
if filesize < 1024:
content = self.sk.recv(filesize)
else:
content = self.sk.recv(1024)
f.write(content)
filesize -= len(content)
self.sk.send(b'ok')
ok = self.sk.recv(11)
if ok == b'download ok':
print('下载成功')
else:
print('下载失败')
print(server_dict['dir_list']) def vip(self):
self.my_send(self.client_dict)
server_dict = self.my_reve()
print(server_dict['return'])
print(server_dict['size'])
print(server_dict['dir_list']) def end(self):
self.my_send(self.client_dict)
self.flag = False
server_dict = self.my_reve()
print(server_dict['return']) def main(self):
main_dict = {
'': self.new_file,
'': self.down_dir,
'': self.up_dir,
'': self.upload,
'': self.download,
'': self.vip,
'': self.end,
}
while 1:
print('1, 在当前目录新建文件夹\n'
'2, 进入下级目录\n'
'3, 返回上级目录\n'
'4, 上传文件\n'
'5, 下载文件\n'
'6, 升级Vip\n'
'7, 退出')
cho_main = input('>>>请输入功能选项ID:').strip()
try:
self.client_dict['opt'] = main_dict[cho_main].__name__
main_dict[cho_main]()
if cho_main == '':
break
except Exception:
print('选项输入不规范') def my_input(self, call_dict):
print('欢迎来到FTP\n1, 登录\n2, 注册')
cho = input('>>>请输入选项ID:').strip()
if cho != '' and cho != '':
return 3
username = input('>>>Username:').strip()
password = input('>>>Password:').strip()
self.client_dict['opt'] = call_dict[cho].__name__
self.client_dict['username'] = username
self.client_dict['password'] = self.my_md5(username, password)
self.my_send(self.client_dict) def main_main(self):
call_dict = {'': self.login, '': self.register}
self.client_dict = {}
flag = self.flag
while flag:
ret = self.my_input(call_dict)
if ret == 3:
print('输入错误')
continue
server_dict = self.my_reve()
print(server_dict['return'])
if server_dict['return'][0] != '错':
print(server_dict['size'])
print(server_dict['dir_list'])
self.main()
flag = self.flag def __call__(self, *args, **kwargs):
self.sk = socket.socket()
self.sk.connect(('127.0.0.1', 9090))
self.main_main()
self.sk.close() if __name__ == '__main__':
client = Myclient()
client() # 这个是 发送的字典的内容, 每次操作, 所对应的键值对 中的值都会发生改变.
# client_dict = {'opt': None, # 选项
# 'username': None, # 用户名
# 'password': None, # 密码
# 'new_dir_name': None, # 新建文件夹的名字
# 'down_dir_name': None, # 打开下一层文件夹的名字
# 'upload_file_name': None, # 上传到ftp里面的文件的名字
# 'upload_file_size': None, # 上传的文件的大小
# 'download_file_name': None, # 下载的文件名字
# }

项目: 更新(二) python 实现大概FTP的功能的更多相关文章

  1. 用 Python 自动监测 GitHub 项目更新

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: GitPython PS:如有需要Python学习资料的小伙伴可以加 ...

  2. 【Quick 3.3】资源脚本加密及热更新(二)资源加密

    [Quick 3.3]资源脚本加密及热更新(二)资源加密 注:本文基于Quick-cocos2dx-3.3版本编写 一.介绍 在前一篇文章中介绍了代码加密,加密方式是XXTEA.对于资源文件来说,同样 ...

  3. 风变编程笔记(二)-Python爬虫精进

    第0关  认识爬虫 1. 浏览器的工作原理首先,我们在浏览器输入网址(也可以叫URL),然后浏览器向服务器传达了我们想访问某个网页的需求,这个过程就叫做[请求]紧接着,服务器把你想要的网站数据发送给浏 ...

  4. 在大型项目上,Python 是个烂语言吗

    Robert Love, Google Software Engineer and Manager on Web Search. Upvoted by Kah Seng Tay, I was the ...

  5. 【开源】SpringBoot&Netty实现仿微信网页版项目更新

    阅读本文约“2.3分钟” 项目更新啦!V1.3.0 还记得那个聊天室的小项目吗? SpringBoot 加 Netty 实现聊天室 没错,这次已经完整进行了版本的替换,酥酥聊天室! 基于原项目的改动, ...

  6. web自动化 基于python+Selenium+PHP+Ftp实现的轻量级web自动化测试框架

    基于python+Selenium+PHP+Ftp实现的轻量级web自动化测试框架   by:授客 QQ:1033553122     博客:http://blog.sina.com.cn/ishou ...

  7. 十二. Python基础(12)--生成器

    十二. Python基础(12)--生成器 1 ● 可迭代对象(iterable) An object capable of returning its members one at a time. ...

  8. 二. Python基础(2)--语法

    二. Python基础(2)--语法 1.实现一个简单的登录系统 '''# 形式1 n = 1 while n < 4:     name = input("请输入姓名\n" ...

  9. H2O中的随机森林算法介绍及其项目实战(python实现)

    H2O中的随机森林算法介绍及其项目实战(python实现) 包的引入:from h2o.estimators.random_forest import H2ORandomForestEstimator ...

随机推荐

  1. sapui5 One or more constraints have not been satisfied.

    Getting error in creating a new project for UI5 One or more constraints have not been satisfied. slo ...

  2. Kinect 人机交互开发实践

    Kinect for Windows SDK 骨骼追踪 —— 对在Kinect视野范围内移动的一个或两个人进行骨骼追踪,可追踪到人体的20个节点 深度摄像头 —— 通过深度传感器获取到视野内的环境三维 ...

  3. codeforces 400 D Dima and Bacteria【并查集 Floyd】

    题意:给出n个点,分别属于k个集合,判断每个集合里面的点的距离都为0,为0的话输出yes,并输出任意两个集合之间的最短路 这道题目有两个地方不会处理, 先是n个点,分别属于k个集合,该怎么记录下来这里 ...

  4. ORM原理

    原理: 1.实现JavaBean的属性到数据库表的字段的映射:        --通过配置文件将JavaBean的属性与数据库表的字段的关联起来 2.映射关系:   一对多,多对一等 持久层(Pers ...

  5. 负载均衡集群总结(Haproxy)

    环境:Centos 6.9,Mysql 8.0 首先要先配置mysql主从复制集,可以参考我的上一篇>>Mysql 主从复制总结(详细) 我的主节点在(master):192.168.11 ...

  6. HDU-1035 Robot Motion 模拟问题(水题)

    题目链接:https://cn.vjudge.net/problem/HDU-1035 水题 代码 #include <cstdio> #include <map> int h ...

  7. BZOJ 3110 [Zjoi2013]K大数查询(整体二分)

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 11654  Solved: 3505[Submit][St ...

  8. 紫书 例题 10-9 UVa 1636 (概率计算)

    小学数学问题 记得分数比较的时候可以交叉相乘(同号) #include<cstdio> #include<cstring> #define REP(i, a, b) for(i ...

  9. 无比强大!Python抓取cssmoban网站的模版并下载

    Python实现抓取http://www.cssmoban.com/cssthemes网站的模版并下载 实现代码 # -*- coding: utf-8 -*- import urlparse imp ...

  10. 智课雅思短语---一、be no exception

    智课雅思短语---一.be no exception 一.总结 一句话总结:…也不例外? …be no exception 1.经济的快速发展? the rapid development of ec ...