zoukankan      html  css  js  c++  java
  • 项目: 更新(二) python 实现大概FTP的功能

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

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

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

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

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

    下面是代码:

    服务器端:

      1 import socketserver
      2 import struct
      3 import pickle
      4 import os
      5 
      6 
      7 class Myserver(socketserver.BaseRequestHandler):
      8     def __init__(self, request, client_address, server):
      9         self.dic_cho = {
     10             'login': self.login,        # 登录
     11             'register': self.register,  # 注册
     12             'new_file': self.new_file,  # 创建新的文件夹
     13             'down_dir': self.down_dir,  # 进入下一层
     14             'up_dir': self.up_dir,      # 进入上一层
     15             'upload': self.upload,      # 上传
     16             'download': self.download,  # 下载
     17             'vip': self.vip,            # 升级vip
     18             'end': self.end,            # 结束
     19             'size': 102400
     20         }
     21         self.flag = False
     22         self.flag_end = True
     23         super().__init__(request, client_address, server)
     24 
     25     def my_reve(self):   # 因为每次接收后的内容都会转成字典, 所以重写了接收的函数
     26         return pickle.loads(self.request.recv(struct.unpack('i', self.request.recv(4))[0]))
     27 
     28     def my_send(self, dic): # 重写了 发送方法.
     29         dic_pic = pickle.dumps(dic)
     30         return self.request.send(struct.pack('i', len(dic_pic)) + dic_pic)
     31 
     32     def isvip(self, server_dict, client_dic):  
     33         """此函数是 login函数的附属函数, 只是用来判断该用户是否为Vip
     34 
     35         :param server_dict: 服务器需要发送的字典
     36         :param client_dic: 服务器接收的客户端发来的字典
     37         :return: None
     38         """
     39         with open('vipinfo', encoding='utf-8') as f:
     40             for name in f:
     41                 if client_dic['username'] == name.strip():
     42                     self.flag = True
     43                     server_dict['return'] = '登录成功, 欢迎尊敬的VIP用户:33[1;33;m%s33[0m 访问ftp' % client_dic['username']
     44                     self.dic_cho['size'] = 10240000
     45                     server_dict['size'] = '容量:(单位:字节)%s/10240000' % os.path.getsize(self.dir_path)
     46                     return
     47 
     48     def login(self, client_dic, server_dict):
     49         self.dir_path = os.path.join(os.path.dirname(__file__), client_dic['username'])
     50         # 第一步 判断用户名+密码 是否正确
     51         with open('info', encoding='utf-8') as f:
     52             for line in f:
     53                 if client_dic['username'] + '	' + client_dic['password'] == line.strip():
     54                     server_dict['return'] = '登录成功, 欢迎%s 用户访问ftp' % client_dic['username']
     55                     server_dict['size'] = f'容量:(单位:字节){os.path.getsize(self.dir_path)}/102400'
     56                     server_dict['dir_list'] = os.listdir(self.dir_path)
     57                     # 第二步 判断此人是不是会员, 有没有vip文件中
     58                     self.isvip(server_dict, client_dic)
     59                     # 第三步, 将字典发送给 客户端并且 结束函数
     60                     self.my_send(server_dict)
     61                     return
     62             server_dict['return'] = '错误:输入错误'
     63             self.my_send(server_dict)
     64 
     65     def register(self, client_dic, server_dict):
     66         self.dir_path = os.path.join(os.path.dirname(__file__), client_dic['username'])
     67         with open('info', encoding='utf-8') as f:
     68             for line in f:
     69                 username, password = line.strip().split('	')
     70                 if client_dic['username'] == username:
     71                     server_dict['return'] = '错误:用户名已存在'
     72                     self.my_send(server_dict)
     73                     return
     74         with open('info', 'a+', encoding='utf-8') as f:
     75             f.write(client_dic['username'] + '	' + client_dic['password'] + '
    ')
     76             self.flag = True
     77             server_dict['return'] = '注册成功,自动登录中'
     78             os.mkdir(client_dic['username'])
     79             server_dict['dir_list'] = os.listdir(self.dir_path)
     80             server_dict['size'] = f'容量:(单位:字节){os.path.getsize(self.dir_path)}/102400'
     81             self.my_send(server_dict)
     82 
     83     def new_file(self, client_dic, server_dict):
     84         """
     85         此函数和下面的六个函数 被执行的前提是客户已经登录成功了,
     86         且已经在客户端显示出来了文件列表, 若没有登录, 该用户访问不到此方法
     87 
     88         此函数的功能是 在当前工作列表中新建文件夹
     89         :param client_dic:
     90         :param server_dict:
     91         :return:
     92         """
     93         new_name = client_dic['new_dir_name']
     94         os.mkdir(os.path.join(self.dir_path, new_name))
     95         server_dict['return'] = '%s 文件夹新建成功' % new_name
     96         self.my_send(server_dict)
     97 
     98     def down_dir(self, client_dic, server_dict):
     99         down_dir_name = client_dic['down_dir_name']
    100         self.dir_path = os.path.join(self.dir_path, down_dir_name)
    101         server_dict['dir_list'] = os.listdir(self.dir_path)
    102         self.my_send(server_dict)
    103 
    104     def up_dir(self, client_dic, server_dict):
    105         dir_path_if = os.path.dirname(self.dir_path)
    106         if dir_path_if == os.path.dirname(__file__):
    107             server_dict['return'] = '已经是最上层目录了'
    108         else:
    109             self.dir_path = dir_path_if
    110         server_dict['dir_list'] = os.listdir(self.dir_path)
    111         self.my_send(server_dict)
    112 
    113     def upload(self, client_dic, server_dict):
    114         filesize = client_dic['upload_file_size']
    115         size = os.path.getsize(self.dir_path)
    116         if filesize+size >= self.dic_cho['size']:
    117             server_dict['return'] = '内存不足'
    118             self.my_send(server_dict)
    119             return
    120         filename = os.path.join(self.dir_path, client_dic['upload_file_name'])
    121         with open(filename, 'wb') as f:
    122             while filesize:
    123                 if filesize < 1024:
    124                     content = self.request.recv(filesize)
    125                 else:
    126                     content = self.request.recv(1024)
    127                 f.write(content)
    128                 filesize -= len(content)
    129         server_dict['return'] = '上传成功'
    130         server_dict['dir_list'] = os.listdir(self.dir_path)
    131         self.my_send(server_dict)
    132 
    133     def download(self, client_dic, server_dict):
    134         filename = os.path.join(self.dir_path, client_dic['download_file_name'])
    135         filesize = os.path.getsize(filename)
    136         server_dict['file_size'] = filesize
    137         self.my_send(server_dict)
    138         with open(filename, 'rb') as f:
    139             while filesize:
    140                 if filesize > 1024:
    141                     content = f.read(filesize)
    142                 else:
    143                     content = f.read(1024)
    144                 self.request.send(content)
    145                 filesize -= len(content)
    146         ok = self.request.recv(2)
    147         print(ok)
    148         self.request.send(b'download ok') if ok == b'ok' else self.request.send(b'download no')
    149 
    150     def vip(self, client_dic, server_dict):
    151         with open('vipinfo', 'r+', encoding='utf-8') as f:
    152             for line in f:
    153                 if client_dic['username'] == line.strip():
    154                     server_dict['return'] = '您已经是尊敬的Vip用户了'
    155                     self.my_send(server_dict)
    156                     return
    157             f.seek(0, 2)
    158             f.write(client_dic['username'] + '
    ')
    159         self.isvip(server_dict, client_dic)
    160         self.my_send(server_dict)
    161 
    162     def end(self, client_dic, server_dict):
    163         self.flag_end = False
    164         server_dict['return'] = '程序结束'
    165         self.my_send(server_dict)
    166 
    167     def handle(self):
    168         server_dict = {}
    169         flag = self.flag_end
    170         while flag:
    171             try:
    172                 client_dic = self.my_reve()
    173                 self.dic_cho[client_dic['opt']](client_dic, server_dict)
    174             except Exception:pass
    175 
    176 
    177 server = socketserver.TCPServer(('127.0.0.1', 9090), Myserver)
    178 server.serve_forever()

    客户端:

      1 import os
      2 import socket
      3 import struct
      4 import pickle
      5 import hashlib
      6 
      7 
      8 class Myclient(socket.socket):
      9     def __init__(self):
     10         super().__init__()
     11         self.dic_cho = {
     12             'login': self.login,  # 登录
     13             'regis': self.register,  # 注册
     14             'new_file': self.new_file,  # 创建新的文件夹
     15             'down_dir': self.down_dir,  # 进入下一层
     16             'up_dir': self.up_dir,  # 进入上一层
     17             'upload': self.upload,  # 上传
     18             'download': self.download,  # 下载
     19             'vip': self.vip,  # 升级vip
     20             'end': self.end,  # 结束
     21         }
     22         self.flag = True
     23 
     24     def my_reve(self):
     25         return pickle.loads(self.sk.recv(struct.unpack('i', self.sk.recv(4))[0]))
     26 
     27     def my_send(self, dic):
     28         dic_pic = pickle.dumps(dic)
     29         return self.sk.send(struct.pack('i', len(dic_pic)) + dic_pic)
     30 
     31     def login(self):pass
     32 
     33     def register(self):pass
     34 
     35     def my_md5(self, user, pwd):
     36         md5_obj = hashlib.md5(user.encode('utf-8'))
     37         md5_obj.update(pwd.encode('utf-8'))
     38         return md5_obj.hexdigest()
     39 
     40     def new_file(self):
     41         new_file_name = input('>>>请输入新建文件夹的名字:').strip()
     42         self.client_dict['new_dir_name'] = new_file_name
     43         self.my_send(self.client_dict)
     44         server_dict = self.my_reve()
     45         print(server_dict['dir_list'])
     46 
     47     def down_dir(self):
     48         down_dir_name = input('>>>请输入下一级文件夹的名字:').strip()
     49         self.client_dict['down_dir_name'] = down_dir_name
     50         self.my_send(self.client_dict)
     51         server_dict = self.my_reve()
     52         print(server_dict['dir_list'])
     53 
     54     def up_dir(self):
     55         self.my_send(self.client_dict)
     56         server_dict = self.my_reve()
     57         print(server_dict['dir_list'])
     58 
     59     def upload(self):
     60         upload_file_path = input('>>>请输入上传文件绝对路径:').strip()
     61         self.client_dict['upload_file_name'] = os.path.basename(upload_file_path)
     62         self.client_dict['upload_file_size'] = os.path.getsize(upload_file_path)
     63         filesize = self.client_dict['upload_file_size']
     64         self.my_send(self.client_dict)
     65         with open(upload_file_path, 'rb') as f:
     66             while filesize:
     67                 if filesize > 1024:
     68                     content = f.read(filesize)
     69                 else:
     70                     content = f.read(1024)
     71                 self.sk.send(content)
     72                 filesize -= len(content)
     73         server_dict = self.my_reve()
     74         print(server_dict['return'])
     75         print(server_dict['dir_list'])
     76 
     77     def download(self):
     78         download_file_name = input('>>>请输入您要下载的文件的名字:').strip()
     79         download_file_path = input('>>>请输入要下载到本地的绝对路径以及对该文件命名:').strip()
     80         self.client_dict['download_file_name'] = download_file_name
     81         self.my_send(self.client_dict)
     82         server_dict = self.my_reve()
     83         filesize = server_dict['file_size']
     84         with open(download_file_path, 'wb') as f:
     85             while filesize:
     86                 if filesize < 1024:
     87                     content = self.sk.recv(filesize)
     88                 else:
     89                     content = self.sk.recv(1024)
     90                 f.write(content)
     91                 filesize -= len(content)
     92             self.sk.send(b'ok')
     93             ok = self.sk.recv(11)
     94             if ok == b'download ok':
     95                 print('下载成功')
     96             else:
     97                 print('下载失败')
     98             print(server_dict['dir_list'])
     99 
    100     def vip(self):
    101         self.my_send(self.client_dict)
    102         server_dict = self.my_reve()
    103         print(server_dict['return'])
    104         print(server_dict['size'])
    105         print(server_dict['dir_list'])
    106 
    107     def end(self):
    108         self.my_send(self.client_dict)
    109         self.flag = False
    110         server_dict = self.my_reve()
    111         print(server_dict['return'])
    112 
    113     def main(self):
    114         main_dict = {
    115             '1': self.new_file,
    116             '2': self.down_dir,
    117             '3': self.up_dir,
    118             '4': self.upload,
    119             '5': self.download,
    120             '6': self.vip,
    121             '7': self.end,
    122         }
    123         while 1:
    124             print('1, 在当前目录新建文件夹
    '
    125                   '2, 进入下级目录
    '
    126                   '3, 返回上级目录
    '
    127                   '4, 上传文件
    '
    128                   '5, 下载文件
    '
    129                   '6, 升级Vip
    '
    130                   '7, 退出')
    131             cho_main = input('>>>请输入功能选项ID:').strip()
    132             try:
    133                 self.client_dict['opt'] = main_dict[cho_main].__name__
    134                 main_dict[cho_main]()
    135                 if cho_main == '7':
    136                     break
    137             except Exception:
    138                 print('选项输入不规范')
    139 
    140     def my_input(self, call_dict):
    141         print('欢迎来到FTP
    1, 登录
    2, 注册')
    142         cho = input('>>>请输入选项ID:').strip()
    143         if cho != '1' and cho != '2':
    144             return 3
    145         username = input('>>>Username:').strip()
    146         password = input('>>>Password:').strip()
    147         self.client_dict['opt'] = call_dict[cho].__name__
    148         self.client_dict['username'] = username
    149         self.client_dict['password'] = self.my_md5(username, password)
    150         self.my_send(self.client_dict)
    151 
    152     def main_main(self):
    153         call_dict = {'1': self.login, '2': self.register}
    154         self.client_dict = {}
    155         flag = self.flag
    156         while flag:
    157             ret = self.my_input(call_dict)
    158             if ret == 3:
    159                 print('输入错误')
    160                 continue
    161             server_dict = self.my_reve()
    162             print(server_dict['return'])
    163             if server_dict['return'][0] != '':
    164                 print(server_dict['size'])
    165                 print(server_dict['dir_list'])
    166                 self.main()
    167                 flag = self.flag
    168 
    169     def __call__(self, *args, **kwargs):
    170         self.sk = socket.socket()
    171         self.sk.connect(('127.0.0.1', 9090))
    172         self.main_main()
    173         self.sk.close()
    174 
    175 
    176 if __name__ == '__main__':
    177     client = Myclient()
    178     client()
    179 
    180 # 这个是 发送的字典的内容, 每次操作, 所对应的键值对 中的值都会发生改变.
    181 # client_dict = {'opt': None,                   # 选项
    182 #                'username': None,              # 用户名
    183 #                'password': None,              # 密码
    184 #                'new_dir_name': None,          # 新建文件夹的名字
    185 #                'down_dir_name': None,         # 打开下一层文件夹的名字
    186 #                'upload_file_name': None,      # 上传到ftp里面的文件的名字
    187 #                'upload_file_size': None,      # 上传的文件的大小
    188 #                'download_file_name': None,    # 下载的文件名字
    189 #                }
  • 相关阅读:
    Asp.net mvc 使用Ajax调用Action 返回数据。
    浅析Asp.net MVC 中Ajax的使用
    Asp.net MVC2中使用Ajax的三种方式
    Ajaxa请求:参数、传递的数据、返回的数据
    ASP.NET MVC 模块与组件——发送邮件
    MVC中根据后台绝对路径读取图片并显示在IMG中
    MVC、一般处理程序hanlder 输出图片文件
    邮箱验证功能原理 语法 属性
    C# 注册邮箱验证的实现代码
    注册页实现激活邮箱验证(asp.net c#) 详细实现
  • 原文地址:https://www.cnblogs.com/Fushengliangnian/p/9374388.html
Copyright © 2011-2022 走看看