python implements an ftp program that can be passed on and concurrently

  • 2020-05-10 18:27:58
  • OfStack

preface

When downloading a file, the most afraid of breaking the line, can not successfully download the complete file. Breakpoint continuation is the process of downloading a file from where it was interrupted, rather than having to download it again. This feature is useful for downloading large files. In this article, I will share with you how to use python to implement an ftp program that can be transmitted and concatenated.

1. The requirements

        1, user md5 authentication

        2. Simultaneous login for multiple users (concurrent)

        3, enter the user's command line mode, support cd switching directory, ls view directory subfiles

4. Execute the command (ipconfig)

        5. Transfer file:

a, support breakpoint continuation

b, display progress bar in transmission

2. The train of thought

1. Client user login and registration:

        a, the client only provides the user name and password, choose to log in or register,

        b, the server side registers and writes the encrypted password to a file, and finally returns to the client side whether it has logged in or registered successfully

2.ls and cd commands

        a, the client enters the command, the server handles it and returns it to the client

3. Execute the order:

        a, the client sends the command to be executed

        b, the number of times the server executes the command and returns the number of times the client needs to receive the command s=r[0]+1, where r=divmod (total result length, 1024)

        c

        d, the server sends the execution result, and the client receives the result through for loop

4. Send file:

        png, the client enters the file path (f.png in beta) and sends the file name and file size

        b, the server side detects whether the specified directory contains the file, if not, returns to the client string s, start, has_recv=0 from scratch
If so, if you need to break it, return to the client how much has_recv has been uploaded

        c, the client receives the return value, seek to has_recv, sends and receives it in a loop, and prints the current progress until the transfer is completed.

Note: this program can receive the user to select the transfer file and execute the command

3. Code

Profile:


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
 
BASE_DIR = os.path.dirname(os.path.dirname(__file__)) # The upper directory of the configuration file 
NEW_FILENAME=os.path.join(BASE_DIR,'view')       # New file directory 
NAME_PWD=os.path.join(BASE_DIR,'db','name_pwd')    # Username and password directory 
USER_FILE=os.path.join(BASE_DIR,'db')

 

Server-side:


#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
import sys,os
import time
import socket
import hashlib
import pickle
import subprocess
import socketserver
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from config import settings
 
 
new=settings.NEW_FILENAME
class Myserver(socketserver.BaseRequestHandler):
 
  def recv_file(self):
    '''
     The file transfer 
    :return:
    '''
    conn=self.request
    a=str(conn.recv(1024),encoding='utf-8')
    file_size,file_name=a.split(',')
    new_file_name=os.path.join(new,file_name)
    if file_name in new:      # Detecting the existence of a file involves a breakpoint 
      has_recv=os.stat(new).st_size # Calculate the temporary file size 
      conn.sendall(bytes(has_recv,encoding='utf-8'))
      with open(new_file_name,'ab') as f: # Append mode 
        while has_recv<=int(file_size):
          data=conn.recv(1024)
          f.write(data)
          has_recv+=len(data)
    else:
      has_recv=0
      conn.sendall(bytes('s',encoding='utf-8')) #  The client receives the string s , from 0 Start sending 
      with open(new_file_name,'wb') as f:
        while has_recv<=int(file_size):
          data=conn.recv(1024)
          f.write(data)
          has_recv+=len(data)
 
  def command(self):
    '''
     Execute the command 
    :return:
    '''
    conn=self.request
    a=conn.recv(1024)
    ret=str(a,encoding='utf-8')
    ret2 = subprocess.check_output(ret, shell=True)
    r=divmod(len(ret2),1024)
    s=r[0]+1     # The number of times the client needs to receive 
    conn.sendall(bytes(str(s),encoding='utf-8'))
    conn.recv(1024) # Confirm the number of times the client has received the request 
 
    conn.sendall(ret2)
 
  def md5(self,pwd):
    '''
     Encrypt the password 
    :param pwd:  password 
    :return:
    '''
    hash=hashlib.md5(bytes('xx7',encoding='utf-8'))
    hash.update(bytes(pwd,encoding='utf-8'))
    return hash.hexdigest()
 
 
  def login(self,usrname,pwd):
    '''
     landing 
    :param usrname:  The user name 
    :param pwd:  password 
    :return: Did you log in successfully? 
    '''
    conn=self.request
    s=pickle.load(open(settings.NAME_PWD,'rb'))
    if usrname in s:
       if s[usrname]==self.md5(pwd):    # Compare it to an encrypted password 
        return True
       else:
        return False
    else:
      return False
 
 
  def regist(self,usrname,pwd):
    '''
     registered 
    :param usrname:  The user name 
    :param pwd:  password 
    :return: Whether the registration is successful or not 
    '''
 
    conn=self.request
    s=pickle.load(open(settings.NAME_PWD,'rb'))
    if usrname in s:
       return False
    else:
      s[usrname]=self.md5(pwd)
      mulu=os.path.join(settings.USER_FILE,usrname)
      os.makedirs(mulu,'a')
      pickle.dump(s,open(settings.NAME_PWD,'wb'))
      return True
 
  def before(self,usrname,pwd,ret):
    '''
     Judge the registration and login, and display the user's detailed directory information, support cd and ls The command 
    :return:
    '''
    conn=self.request
    if ret=='1':
      r=self.login(usrname,pwd)
      if r:
        conn.sendall(bytes('y',encoding='utf-8'))
      else:
        conn.sendall(bytes('n',encoding='utf-8'))
    elif ret=='2':
      # print(usrname,pwd)
      r=self.regist(usrname,pwd)
      if r:
        conn.sendall(bytes('y',encoding='utf-8'))
      else:
        conn.sendall(bytes('n',encoding='utf-8'))
  def usr_file(self,usrname):
    '''
     Display user directory details, supported cd and ls The command 
    :param usrname:  The user name 
    :return:
    '''
    conn=self.request
    conn.recv(1024)
    mulu=os.path.join(settings.USER_FILE,usrname)
    conn.sendall(bytes(mulu,encoding='utf-8'))
    while True:
      b=conn.recv(1024)
      ret=str(b,encoding='utf-8')
      try:
        a,b=ret.split(' ',1)
      except Exception as e:
        a=ret
      if a=='cd':
        if b=='..':
          mulu=os.path.dirname(mulu)
        else:
          mulu=os.path.join(mulu,b)
        conn.sendall(bytes(mulu,encoding='utf-8'))
      elif a=='ls':
        ls=os.listdir(mulu)
        print(ls)
        a=','.join(ls)
        conn.sendall(bytes(a,encoding='utf-8'))
      elif a=='q':
        break
 
 
  def handle(self):
    conn=self.request
    conn.sendall(bytes('welcome',encoding='utf-8'))
    b=conn.recv(1024)
    ret=str(b,encoding='utf-8')
    print(ret)
    conn.sendall(bytes('b ok',encoding='utf-8'))
    c=conn.recv(1024)
    r=str(c,encoding='utf-8')
    usrname,pwd=r.split(',')
    self.before(usrname,pwd,ret) # Login or register for verification 
    self.usr_file(usrname) # Display user directory details, supported cd and ls The command 
    while True:
      a=conn.recv(1024)
      conn.sendall(bytes(' received a',encoding='utf-8'))
      ret=str(a,encoding='utf-8')
      if ret=='1':
        self.recv_file()
        # conn.sendall(bytes('file ok',encoding='utf-8'))
      elif ret=='2':
        self.command()
      elif ret=='q':
        break
      else:
        pass
 
if __name__=='__main__':
  sever=socketserver.ThreadingTCPServer(('127.0.0.1',9999),Myserver)
  sever.serve_forever()

Client:


#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
import sys
import time
import os
import socket
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from config import settings
 
 
 
def send_file(file_path):
  '''
   Send a file 
  :param file_name: The file name 
  :return:
  '''
  size=os.stat(file_path).st_size
  file_name=os.path.basename(file_path)
  obj.sendall(bytes(str(size)+','+file_name,encoding='utf-8')) # Send file size and file name 
  ret=obj.recv(1024)  # How much reception has been sent 
  r=str(ret,encoding='utf-8')
  if r=='s': # File does not exist, start from scratch 
    has_send=0
  else:  # File exists 
    has_send=int(r)
 
  with open(file_path,'rb') as f:
    f.seek(has_send) # Locate to the location that has been passed 
    while has_send<size:
      data=f.read(1024)
      obj.sendall(data)
      has_send+=len(data)
      sys.stdout.write('\r') # Empty file contents 
      time.sleep(0.2)
      sys.stdout.write(' Has been sent %s%%|%s' %(int(has_send/size*100),(round(has_send/size*40)*' u ')))
      sys.stdout.flush()  # Force memory out 
    print(" Uploaded successfully \n")
 
def command(command_name):
  '''
   Execute the command 
  :param command_name:
  :return:
  '''
  obj.sendall(bytes(command_name,encoding='utf-8'))
  ret=obj.recv(1024) # The number of times a receive command needs to be received 
  obj.sendall(bytes(' Number of received ',encoding='utf-8'))
  r=str(ret,encoding='utf-8')
  for i in range(int(r)): # Common need reception int(r) time 
    ret=obj.recv(1024) # Wait for the client to send 
    r=str(ret,encoding='GBK')
    print(r)
 
def login(usrname,pwd):
  '''
   landing 
  :param usrname: The user name 
  :param pwd: password 
  :return: Did you log in successfully? 
  '''
  obj.sendall(bytes(usrname+','+pwd,encoding='utf-8'))
  ret=obj.recv(1024)
  r=str(ret,encoding='utf-8')
  if r=='y':
    return 1
  else:
    return 0
 
def regist(usrname,pwd):
  '''
   registered 
  :param usrname: The user name 
  :param pwd: password 
  :return: Whether the registration is successful or not 
  '''
  obj.sendall(bytes(usrname+','+pwd,encoding='utf-8'))
  ret=obj.recv(1024)
  r=str(ret,encoding='utf-8')
  if r=='y':
    return 1
  else:
    return 0
def before(usrname,pwd):
  '''
   Select login or register, display user's detailed directory information, support cd and ls The command 
  :return:
  '''
  a=input(' Please select a 1. landing  2. registered ')
  obj.sendall(bytes(a,encoding='utf-8'))
  obj.recv(1024)
  if a=='1':
    ret=login(usrname,pwd)
    if ret:
      print(' Log in successfully ')
      return 1
    else:
      print(' Wrong username or password ')
      return 0
  elif a=='2':
    ret=regist(usrname,pwd)
    if ret:
      print(' Registered successfully ')
      return 1
    else:
      print(' The username already exists ')
      return 0
def usr_file(usrname):
  obj.sendall(bytes(' Print the user file path ',encoding='utf-8'))
  ret=obj.recv(1024) # Wait for the client to send 
  r=str(ret,encoding='utf-8')
  print(r)
  while True:
    a=input(' The input cd Switch directories, ls For directory details, q exit >:')
 
    obj.sendall(bytes(a,encoding='utf-8'))
    if a=='q':
      break
    else:
      ret=obj.recv(1024) # Wait for the client to send 
      r=str(ret,encoding='utf-8')
      if len(r)==1:# Judgment is cd The results are ls The result of ( ls only 1 Subdirectories can also be printed directly.) 
        print(r)
      else:
        li=r.split(',')
        for i in li:
          print(i) # Print each 1 subdirectory 
 
def main(usrname,pwd):
  ret=obj.recv(1024) # Wait for the client to send 
  r=str(ret,encoding='utf-8')
  print(r)
  result=before(usrname,pwd)# Login or register 
  if result:
    usr_file(usrname)
    while True:
      a=input(' Please select a 1. Transfer files  2. Execute the command  q exit :')
      obj.sendall(bytes(str(a),encoding='utf-8'))
      ret=obj.recv(1024) # Confirm receipt a
      r=str(ret,encoding='utf-8')
      print(r)
      if a=='1':
        b=input(' Please enter the file path (the beta path is: f.png ) :')
        # b='f.png'
        if os.path.exists(b):
          send_file(b)
          obj.sendall(bytes('hhe',encoding='utf-8'))
          # obj.recv(1024)
      elif a=='2':
        b=input(' Please enter the command:')
        command(b)
      elif a=='q':
        break
      else:
        print(' Input error ')
 
  obj.close()
 
if __name__ == '__main__':
  obj=socket.socket() # Create client socket object 
  obj.connect(('127.0.0.1',9999))
  usrname=input(' Please enter a user name ')
  pwd=input(' Please enter your password ')
  main(usrname,pwd)

conclusion

This is the python implementation can be interrupted and concurrent ftp program all content, the article is very detailed, I hope to help you learn or use python to bring 1.


Related articles: