服务器利用 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, # 下载的文件名字
# }

最新文章

  1. 树莓派(rasperberry pi 2)上装mysql远程无法访问
  2. 【HDU 4451 Dressing】水题,组合数
  3. Python 新浪微博中提取最常见转载的微博转载了几次,username,内容
  4. 深入理解HTTP协议(转)
  5. angular.js添加自定义服务依赖项方法
  6. 契约测试框架-Pact实践
  7. 如何使用python将MySQL中的查询结果导出为Excel----xlwt的使用
  8. Python定时任务
  9. 微信小程序setData()方法的详解以及对数组/json操作
  10. django-rest-framework-jwt
  11. UI自动化(九)Css Selector
  12. [BZOJ3745][COCI2015]Norma[分治]
  13. 遗传算法入门C1
  14. 用javascript获得地址栏参数的两种方法
  15. Linux文件扩展思考随笔
  16. SpringBoot2.0+ElasticSearch网盘搜索实现
  17. PowerDesigner导出word表结构
  18. 巨蟒python全栈开发linux之cento9
  19. 解决css的float父div没有高度
  20. R 语言实现求导

热门文章

  1. ajax中Post和Get请求方式的区别?
  2. Edge浏览器开发人员工具
  3. 关于linq使用建议
  4. 如何用Java实现反转排序
  5. phpstorm10安装并汉化
  6. SSL和SSH
  7. Python组织文件 实践:查找大文件、 用Mb、kb显示文件尺寸 、计算程序运行时间
  8. 关于memset赋最值
  9. 七 HBase表结构设计
  10. linux 下的select函数