• Python-Socketserver实现FTP,文件上传、下载


    一、Socketserver实现FTP,文件上传、下载

      目录结构

        

    1、socketserver实现ftp文件上传下载,可以同时多用户登录、上传、下载

      效果图:

      

    二、上面只演示了下载,上传也是一样的,来不及演示了,上代码

      

     1、客户端

      1 import socket,hashlib,os,json,sys,time
      2 
      3 
      4 
      5 class Ftpclient(object):
      6 
      7 
      8     def __init__(self):
      9         self.client = socket.socket()
     10 
     11     def connect(self,ip,port):
     12         self.client.connect((ip, port))
     13 
     14 
     15     def help(self):
     16         msg='''
     17         ls 
     18 
     19         pwd 
     20         
     21         cd ..
     22         
     23         get filename
     24         
     25         put filename
     26         
     27         '''
     28         print(msg)
     29 
     30 
     31     def interactive(self):
     32         """
     33         客户端入口
     34         :return:
     35         """
     36         while True:
     37             verify = self.authenticate() #服务器端认证
     38             if verify:
     39                 while True:
     40                     cmd = input('输入命令  >>').strip()
     41                     if len(cmd) == 0:continue
     42                     cmd_str = cmd.split()[0]
     43                     if hasattr(self,'cmd_%s' %cmd_str):
     44                         func = getattr(self,'cmd_%s' %cmd_str)
     45                         func(cmd)
     46                     else:
     47                         self.help()
     48 
     49 
     50     def cmd_put(self,*args):
     51         """
     52         上传文件
     53         :param args:
     54         :return:
     55         """
     56         cmd_solit = args[0].split()
     57         start_time = self.alltime()  # 开始时间
     58         if len(cmd_solit) > 1:
     59             filename = cmd_solit[1]
     60             if os.path.isfile(filename):
     61                 filesize = os.stat(filename).st_size
     62                 msg_dic = {
     63                     'filename':filename,
     64                     'size':filesize,
     65                     'overridden':True,
     66                     'action':cmd_solit[0]
     67                 }
     68 
     69                 self.client.send( json.dumps(msg_dic).encode('utf-8'))
     70                 server_respinse=self.client.recv(1024)  #防止粘包,等服务器确认返回
     71                 print('文件开始上传',server_respinse)
     72                 client_size = 0
     73                 f = open(filename,'rb')
     74                 for line in f:
     75                     client_size += self.client.send(line)
     76                     self.processBar(client_size,filesize)  #进度条
     77                 else:
     78                     print('文件传输完毕,大小为 %s'%client_size)
     79                     end_time = self.alltime()              # 结束时间
     80                     print('本次上传花费了%s 秒'%self.alltime(end_time,start_time))
     81                     f.close()
     82             else:
     83                 print(filename,'文件不存在')
     84         else:
     85             print('输入有误!')
     86 
     87 
     88     def cmd_get(self,*args):
     89         """
     90         下载文件
     91         :param args:
     92         :return:
     93         """
     94         cmd_solit = args[0].split()
     95         start_time = self.alltime()  # 开始时间
     96         filename = cmd_solit[1]
     97         if len(cmd_solit) > 1:
     98             msg_dic = {
     99                 'filename': filename,
    100                 'size': '',
    101                 'overridden': True,
    102                 'action': cmd_solit[0],
    103                 'file_exist':''
    104             }
    105             self.client.send(json.dumps(msg_dic).encode('utf-8'))
    106             self.data = self.client.recv(1024).strip()
    107 
    108             cmd_dic = json.loads(self.data.decode('utf-8'))
    109             print(cmd_dic)
    110             if cmd_dic['file_exist']:
    111                 if os.path.isfile(filename):
    112                     f = open(filename + '.new', 'wb')
    113                 else:
    114                     f = open(filename, 'wb')
    115 
    116                 self.client.send(b'200 ok')     #防止粘包,等服务器确认返回
    117                 client_size = 0
    118                 filesize = cmd_dic['size']
    119                 m = hashlib.md5()
    120                 while client_size <  filesize:
    121                     data=self.client.recv(1024)
    122                     f.write(data)
    123                     client_size +=len(data)
    124                     m.update(data)
    125                     self.processBar(client_size, filesize)
    126                 else:
    127                     print('下载完毕')
    128                     end_time = self.alltime()   # 结束时间
    129                     print('本次下载花费了%s 秒' % self.alltime(end_time, start_time))
    130                     f.close()
    131                     new_file_md5 = m.hexdigest()
    132                     server_file_md5 = self.client.recv(1024)
    133                     print('MD5', server_file_md5,new_file_md5)
    134 
    135             else:
    136                 print('下载的 %s文件不存在'%filename)
    137 
    138         else:
    139             print('输入有误!')
    140 
    141 
    142     def cmd_dir(self,*arge):
    143         cmd_solit = arge[0].split()
    144         if len(cmd_solit) > 0:
    145             msg_dic = {
    146                 'action': cmd_solit[0]
    147             }
    148             self.client.send(json.dumps(msg_dic).encode())
    149             cmd_dir = self.client.recv(1024)
    150             print(cmd_dir.decode())
    151 
    152         else:
    153             print('输入错误!')
    154 
    155 
    156 
    157     def alltime(self,*args):
    158         """
    159         计算上传、下载时间
    160         :param args:
    161         :return:
    162         """
    163         if args:
    164             return round(args[0] - args[1])
    165         else:
    166             return time.time()
    167 
    168 
    169     def processBar(self,num, total):
    170         """
    171         进度条
    172         :param num:文件总大小
    173         :param total: 已存入文件大小
    174         :return:
    175         """
    176         rate = num / total
    177         rate_num = int(rate * 100)
    178         if rate_num == 100:
    179             r = '
    %s>%d%%
    ' % ('=' * int(rate_num /3), rate_num,)
    180         else:
    181             r = '
    %s>%d%%' % ('=' * int(rate_num /3), rate_num,)
    182         sys.stdout.write(r)
    183         sys.stdout.flush
    184 
    185 
    186     def authenticate(self):
    187         """
    188         用户加密认证
    189         :return:
    190         """
    191         username = input('输入用户名:>>')
    192         password = input('输入密码:>>')
    193         m = hashlib.md5()
    194         if len(username) > 0 and len(password) >0:
    195             username = ''.join(username.split())
    196             password = ''.join(password.split())
    197             m.update(username.encode('utf-8'))
    198             m.update(password.encode('utf-8'))
    199 
    200             m = {
    201                 'username':username,
    202                 'password':password,
    203                 'md5':m.hexdigest()
    204             }
    205             self.client.send(json.dumps(m).encode('utf-8'))
    206             server_user_md5 = self.client.recv(1024).strip()
    207             print(server_user_md5.decode())
    208             if server_user_md5.decode() == 'success':
    209                 print('登录成功!')
    210                 return 'ok'
    211             else:
    212                 print('用户名密码错误!')
    213         else:
    214             print('请输入用户名密码')
    215 
    216 
    217 
    218 f = Ftpclient()
    219 f.connect('localhost',9999)
    220 f.interactive()

    2、服务器端

      1 import socketserver,json,os,hashlib,sys,paramiko
      2 
      3 import settings
      4 
      5 class Mysocketserver(socketserver.BaseRequestHandler):
      6 
      7 
      8 
      9     def put(self,*args):
     10         '''
     11         接受客户端上传文件
     12         :return:
     13         '''
     14         cmd_dic = args[0]
     15         filename = cmd_dic['filename']  #获取文件名
     16         filesize= cmd_dic['size']       #获取文件大小(字节)
     17 
     18         if os.path.isfile(filename):    #判断文件是否存在
     19             f = open(filename + '.new','wb')
     20         else:
     21             f = open(filename, 'wb')
     22 
     23         self.request.send(b'200 ok')    #防止粘包
     24         print('%s 文件开始上传' % self.client_address[0])
     25         received_size = 0
     26         while received_size < filesize:
     27             data = self.request.recv(1024)
     28             f.write(data)
     29             received_size += len(data)
     30         else:
     31             print('文件传输完毕',filename)
     32 
     33 
     34     def get(self, *args):
     35         '''
     36         客户端下载文件
     37        :return:
     38        '''
     39         msg_dic = {
     40             'filename': '',
     41             'size': '',
     42             'overridden': True,
     43             'action': '',
     44             'file_exist': ''
     45         }
     46 
     47         cmd_solit = args[0]
     48         filename = cmd_solit['filename']
     49         file_exist = os.path.isfile(filename)
     50         msg_dic['file_exist'] = file_exist
     51         print(file_exist)
     52         if file_exist:
     53             filesize = os.stat(filename).st_size
     54 
     55             msg_dic['filename'] = filename
     56             msg_dic['size'] = filesize
     57             msg_dic['action'] = cmd_solit['action']
     58 
     59             self.request.send(json.dumps(msg_dic).encode('utf-8'))
     60             server_respang = self.request.recv(1024)  #防止粘包
     61             print('开始传输',server_respang)
     62             f = open(filename,'rb')
     63             m = hashlib.md5()
     64             for lien in f:
     65                 m.update(lien)
     66                 self.request.send(lien)
     67             else:
     68                 print('传输完成')
     69                 f.close()
     70                 self.request.send(m.hexdigest().encode())
     71         else:
     72             print('文件不存在')
     73             self.request.send(json.dumps(msg_dic).encode('utf-8'))
     74 
     75 
     76 
     77     def client_authentication(self):
     78         """
     79         客户端认证
     80         :return:
     81         """
     82         self.client_user= self.request.recv(1024).strip()
     83         client_xinxi = json.loads(self.client_user.decode('utf-8'))
     84         try:
     85             with open(settings.school_db_file + client_xinxi['username'],'rb') as f:
     86                 data = json.load(f)
     87                 if data['md5'] == client_xinxi['md5']: #判断用户输入是否和服务器端MD5是否一致
     88                     print('验证成功!')
     89                     self.request.send('success'.encode())
     90                     return 'success'
     91                 else:
     92                     self.request.send('error'.encode())
     93         except Exception as e:
     94             print('没有此用户',e)
     95             self.request.send('error'.encode())
     96 
     97 
     98     def dir(self,*args):
     99         """
    100         查看目录
    101         :param args:
    102         :return:
    103         """
    104         cmd_split = args[0]
    105         dd=cmd_split['action']
    106         result_os = os.popen(dd).read()
    107         self.request.send(result_os.encode())
    108 
    109 
    110 
    111     def handle(self):
    112         """
    113         服务器端入口
    114         :return:
    115         """
    116         while True:
    117             try:
    118                 success = self.client_authentication()
    119                 if success:
    120                     self.data=self.request.recv(1024).strip()
    121                     cmd_dic = json.loads(self.data.decode('utf-8'))
    122                     action = cmd_dic['action']
    123                     if hasattr(self,action):
    124                         func = getattr(self,action)
    125                         func(cmd_dic)
    126             except ConnectionResetError as e:
    127                 print('连接断开',self.client_address[0])
    128                 break
    129 
    130 
    131 
    132 if __name__ == '__main__':
    133 
    134     HOST,PORT='localhost',9999
    135     server=socketserver.ThreadingTCPServer((HOST,PORT),Mysocketserver)
    136     server.serve_forever()
    settings.py 文件
    1 import os
    2 
    3 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    4 
    5 DB_FILE = os.path.join(BASE_DIR, "data\")
    6 
    7 school_db_file = os.path.join(DB_FILE)
    8 print(school_db_file)

    data里两个做测试的文件,

    1 alex 文件内容:
    2 {"username": "alex", "password": "123456", "md5": "94e4ccf5e2749b0bfe0428603738c0f9"}
    kml123456文件内容:
    {"username": "kml123456", "password": "123456","md5": "a791650e70ce08896e3dafbaa7598c26"}

    到这里差不多就没了,

     
  • 相关阅读:
    luogu P1396 营救
    luogu P2009 跑步
    2017 9 22
    2017 9 22 模拟赛T2
    2017 9 21
    luogu P1433 吃奶酪
    luogu p1867【Mc生存】经验值
    luogu p1387 最大正方形
    单例模式1
    Java 设计模式
  • 原文地址:https://www.cnblogs.com/km-thonder/p/12579302.html
Copyright © 2020-2023  润新知