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.