Python socket server realizes FTP, file upload and download

Time:2020-5-31

1、 Socket server realizes FTP, file upload and download

 

  directory structure

    

 

 

 

1. Socket server realizes FTP file upload and download, and can log in, upload and download multiple users at the same time

design sketch:

  

 

2、 The above only demonstrates download, upload is the same, too late to demonstrate, on the code

  

 

1. Client

import socket,hashlib,os,json,sys,time
 
 
 
 class Ftpclient(object):
 
 
     def __init__(self):
         self.client = socket.socket()
 
     def connect(self,ip,port):
         self.client.connect((ip, port))
 
 
     def help(self):
         msg='''
         ls 
 
         pwd 
         
         cd ..
         
         get filename
         
         put filename
         
         '''
         print(msg)
 
 
     def interactive(self):
         """
         Client portal
         :return:
         """
         while True:
             verify =  self.authenticate () server authentication
             if verify:
                 while True:
                     CMD = input ('input command > > '). Strip()
                     if len(cmd) == 0:continue
                     cmd_str = cmd.split()[0]
                     if hasattr(self,'cmd_%s' %cmd_str):
                         func = getattr(self,'cmd_%s' %cmd_str)
                         func(cmd)
                     else:
                         self.help()
 
 
     def cmd_put(self,*args):
         """
         Upload file
         :param args:
         :return:
         """
         cmd_solit = args[0].split()
         start_ time =  self.alltime () start time
         if len(cmd_solit) > 1:
             filename = cmd_solit[1]
             if os.path.isfile(filename):
                 filesize = os.stat(filename).st_size
                 msg_dic = {
                     'filename':filename,
                     'size':filesize,
                     'overridden':True,
                     'action':cmd_solit[0]
                 }
 
                 self.client.send( json.dumps(msg_dic).encode('utf-8'))
                 server_ respinse= self.client.recv (1024) prevent package sticking, wait for the server to confirm and return
                 Print ('File start upload ', server_ respinse)
                 client_size = 0
                 f = open(filename,'rb')
                 for line in f:
                     client_size += self.client.send(line)
                     self.processBar (client_ Size, filesize) progress bar
                 else:
                     Print ('File transfer completed, size% s'% client_ size)
                     end_ time =  self.alltime () end time
                     Print ('This upload took% s seconds ` self.alltime (end_ time,start_ time))
                     f.close()
             else:
                 Print (filename, 'file does not exist')
         else:
             Print ('wrong input! )
 
 
     def cmd_get(self,*args):
         """
         Download File
         :param args:
         :return:
         """
         cmd_solit = args[0].split()
         start_ time =  self.alltime () start time
         filename = cmd_solit[1]
         if len(cmd_solit) > 1:
             msg_dic = {
                 'filename': filename,
                 'size': '',
                 'overridden': True,
                 'action': cmd_solit[0],
                 'file_exist':''
             }
             self.client.send(json.dumps(msg_dic).encode('utf-8'))
             self.data = self.client.recv(1024).strip()
 
             cmd_dic = json.loads(self.data.decode('utf-8'))
             print(cmd_dic)
             if cmd_dic['file_exist']:
                 if os.path.isfile(filename):
                     f = open(filename + '.new', 'wb')
                 else:
                     f = open(filename, 'wb')
 
                 self.client.send (B'200 OK ') (prevent package sticking, wait for the server to confirm and return
                 client_size = 0
                 filesize = cmd_dic['size']
                 m = hashlib.md5()
                 while client_size <  filesize:
                     data=self.client.recv(1024)
                     f.write(data)
                     client_size +=len(data)
                     m.update(data)
                     self.processBar(client_size, filesize)
                 else:
                     Print ('download completed ')
                     end_ time =  self.alltime () end time
                     Print ('This download took% s seconds'%) self.alltime (end_ time, start_ time))
                     f.close()
                     new_file_md5 = m.hexdigest()
                     server_file_md5 = self.client.recv(1024)
                     print('MD5', server_file_md5,new_file_md5)
 
             else:
                 Print ('downloaded% s file does not exist '% filename)
 
         else:
             Print ('wrong input! )
 
 
     def cmd_dir(self,*arge):
         cmd_solit = arge[0].split()
         if len(cmd_solit) > 0:
             msg_dic = {
                 'action': cmd_solit[0]
             }
             self.client.send(json.dumps(msg_dic).encode())
             cmd_dir = self.client.recv(1024)
             print(cmd_dir.decode())
 
         else:
             Print ('input error! )
 
 
 
     def alltime(self,*args):
         """
         Calculate upload and download time
         :param args:
         :return:
         """
         if args:
             return round(args[0] - args[1])
         else:
             return time.time()
 
 
     def processBar(self,num, total):
         """
         progress bar
         : param num: total file size
         : param total: saved file size
         :return:
         """
         rate = num / total
         rate_num = int(rate * 100)
         if rate_num == 100:
             r = '\r%s>%d%%\n' % ('=' * int(rate_num /3), rate_num,)
         else:
             r = '\r%s>%d%%' % ('=' * int(rate_num /3), rate_num,)
         sys.stdout.write(r)
         sys.stdout.flush
 
 
     def authenticate(self):
         """
         User encryption authentication
         :return:
         """
         Username = input ('enter user name: > > ')
         Password = input ('input password: > > ')
         m = hashlib.md5()
         if len(username) > 0 and len(password) >0:
             username = ''.join(username.split())
             password = ''.join(password.split())
             m.update(username.encode('utf-8'))
             m.update(password.encode('utf-8'))
 
             m = {
                 'username':username,
                 'password':password,
                 'md5':m.hexdigest()
             }
             self.client.send(json.dumps(m).encode('utf-8'))
             server_user_md5 = self.client.recv(1024).strip()
             print(server_user_md5.decode())
             if server_user_md5.decode() == 'success':
                 Print ('login succeeded! )
                 return 'ok'
             else:
                 Print ('wrong username and password! )
         else:
             Print ('Please enter username and password ')
 
 
 
 f = Ftpclient()
 f.connect('localhost',9999)
 f.interactive()

2. Server side

import socketserver,json,os,hashlib,sys,paramiko
 
 import settings
 
 class Mysocketserver(socketserver.BaseRequestHandler):
 
 
 
     def put(self,*args):
         '''
         Accept client upload file
         :return:
         '''
         cmd_dic = args[0]
         filename = cmd_ DIC ['filename '] (get filename)
         filesize= cmd_ DIC ['size '] (get file size in bytes)
 
         If os.path.isfile (filename): ා judge whether the file exists
             f = open(filename + '.new','wb')
         else:
             f = open(filename, 'wb')
 
         self.request.send (B'200 OK ') to prevent sticking
         Print (""% s file starts to upload '% " self.client_ address[0])
         received_size = 0
         while received_size < filesize:
             data = self.request.recv(1024)
             f.write(data)
             received_size += len(data)
         else:
             Print ('File transfer completed ', filename)
 
 
     def get(self, *args):
         '''
         Client download file
        :return:
        '''
         msg_dic = {
             'filename': '',
             'size': '',
             'overridden': True,
             'action': '',
             'file_exist': ''
         }
 
         cmd_solit = args[0]
         filename = cmd_solit['filename']
         file_exist = os.path.isfile(filename)
         msg_dic['file_exist'] = file_exist
         print(file_exist)
         if file_exist:
             filesize = os.stat(filename).st_size
 
             msg_dic['filename'] = filename
             msg_dic['size'] = filesize
             msg_dic['action'] = cmd_solit['action']
 
             self.request.send(json.dumps(msg_dic).encode('utf-8'))
             server_ respang =  self.request.recv (1024) anti sticking
             Print ('Start transfer ', server_ respang)
             f = open(filename,'rb')
             m = hashlib.md5()
             for lien in f:
                 m.update(lien)
                 self.request.send(lien)
             else:
                 Print ('transfer complete ')
                 f.close()
                 self.request.send(m.hexdigest().encode())
         else:
             Print ('File does not exist ')
             self.request.send(json.dumps(msg_dic).encode('utf-8'))
 
 
 
     def client_authentication(self):
         """
         Client authentication
         :return:
         """
         self.client_user= self.request.recv(1024).strip()
         client_xinxi = json.loads(self.client_user.decode('utf-8'))
         try:
             with open(settings.school_db_file + client_xinxi['username'],'rb') as f:
                 data = json.load(f)
                 if data['md5'] == client_ Xinxi ['md5 ']: judge whether the user input is consistent with the server MD5
                     Print ('verification succeeded! )
                     self.request.send('success'.encode())
                     return 'success'
                 else:
                     self.request.send('error'.encode())
         except Exception as e:
             Print ('No such user ', e)
             self.request.send('error'.encode())
 
 
     def dir(self,*args):
         """
         View catalog
         :param args:
         :return:
         """
         cmd_split = args[0]
         dd=cmd_split['action']
         result_os = os.popen(dd).read()
         self.request.send(result_os.encode())
 
 
 
     def handle(self):
         """
         Server side portal
         :return:
         """
         while True:
             try:
                 success = self.client_authentication()
                 if success:
                     self.data=self.request.recv(1024).strip()
                     cmd_dic = json.loads(self.data.decode('utf-8'))
                     action = cmd_dic['action']
                     if hasattr(self,action):
                         func = getattr(self,action)
                         func(cmd_dic)
             except ConnectionResetError as e:
                 Print ('disconnected ', self.client_ address[0])
                 break
 
 
 
 if __name__ == '__main__':
 
     HOST,PORT='localhost',9999
     server=socketserver.ThreadingTCPServer((HOST,PORT),Mysocketserver)
     server.serve_forever()

 

settings.py  file
 import os
 
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
 DB_FILE = os.path.join(BASE_DIR, "data\")
 
 school_db_file = os.path.join(DB_FILE)
 print(school_db_file)

Data,

Alex file content:
 {"username": "alex", "password": "123456", "md5": "94e4ccf5e2749b0bfe0428603738c0f9"}
Kml123456 file content:
{"username": "kml123456", "password": "123456","md5": "a791650e70ce08896e3dafbaa7598c26"}

 

It’s almost gone,