Objective
When downloading files, the most afraid of breaking the line, can not successfully download the full file. The continuation of the breakpoint is the download from where the file was interrupted without having to download it again. This feature is useful for downloading larger files. So this article is to share with you how to use the Python implementation can be a breakpoint continuation and concurrent FTP programs.
I. Requirements
1, User MD5 certification
2. Support multiple users to login at the same time (concurrent)
3, enter the user's command line mode, support CD switching directory, ls view directory sub-Files
4. Execution order (ipconfig)
5. Transfer files:
A, support the continuation of the breakpoint
B, the transmission of the display progress bar
Second, train of thought
1. Client User Login and registration:
A, the client only provides user name and password, select login or registration,
b, the server side to register and write the encrypted password to the file, and finally return to the client whether to sign in or register successfully
2.ls and CD commands
A, client input commands, server-side processing and return to the client
3. Executive Order:
A, the client sends the command that needs to be executed
b, the server side executes the command and returns the number of times the client needs to receive the command s=r[0]+1, where R=divmod (total length of result, 1024)
C, the number of clients received, told the server has received
D, the server sends execution results, and the client makes a for loop to receive the result
4. Send the file:
A, client input file path (Beta path is: f.png), send file name and file size
B, server-side detect whether the specified directory contains the file, if not, return to the client string s, that is, from the beginning to send start,has_recv=0
If there is, that is, the need for a continuation of the breakpoint, returned to the client has been uploaded how many has_recv
C, the client receives the return value, and seek to has_recv position, carries on the circulation to send and receive, prints the current progress, until transmits completes.
Note: This program can be recycled to receive the user to select the transfer file and execute the command
Third, the Code
Configuration file:
#!/usr/bin/env python
#-*-coding:utf-8-*-
import os
base_dir = Os.path.dirname (Os.path.dirname (__file_ _) #配置文件的上层目录
new_filename=os.path.join (base_dir, ' view ') #新文件目录
name_pwd=os.path.join (Base_dir, ' DB ', ' name_pwd ') #用户名和密码目录
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 Impo RT 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): ' File transfer: return: ' Conn=self.request a=str (CONN.R ECV (1024), encoding= ' Utf-8 ') file_size,file_name=a.split (', ') new_file_name=os.path.join (new,file_name) if file _name in NEW: #检测文件是否已存在, involving breakpoint Has_recv=os.stat (new). St_size #计算临时文件大小 Conn.sendall bytes (has_recv,encod ing= ' Utf-8 ') with open (New_file_name, ' AB ") as F: #追加模式 while Has_recv<=int (file_size): Data=co NN.RECV (1024) f.write (data) Has_recv+=len (data) else:has_recv=0 Conn.sendall (' s
', encoding= ' Utf-8 ') # Client receives string s, starting from 0 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 command: return: ' ' conn=self.request a=conn.recv (1024) ret=str (A,enc oding= ' utf-8 ') Ret2 = Subprocess.check_output (ret, shell=true) r=divmod (Len (Ret2), 1024) s=r[0]+1 #客户端需要接收的 Number of times Conn.sendall (bytes (str (s), encoding= ' Utf-8 ')) CONN.RECV (1024) #确认客户端收到需要接收的次数 Conn.sendall (Ret2) def m D5 (SELF,PWD): "Encrypt the password:p aram 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): " Login:p Aram Usrname: Username:p aram pwd: Password: return: Login succeeded ' Conn=self.request s=pickle.load (open (SE
Ttings.name_pwd, ' RB ')) if usrname in S:if s[usrname]==self.md5 (PWD): #和加密后的密码进行比较 return True Else:return FAlse Else:return False def regist (self,usrname,pwd): ' Registered:p Aram Usrname: username:p Aram PW D: Password: return: Whether to register successfully ' 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 registration and login, and display user's detailed catalog information, support CD and ls command: return: ' Conn=self.request I
F 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,PW D) if R:conn.sendall (bytes (' Y ', encoding= ' Utf-8 ')) Else:conn.sendall (bytes (' n ', encoding= ') utf- 8 ') def usr_file (self,usrname): ' ExhibitionShow user's detailed catalog information, support CD and ls command:p Aram usrname: User name: return: "' Conn=self.request conn.recv (1024) MULU=OS.PA Th.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.senda
ll (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.req Uest conn.sendall (bytes (' Welcome ', encoding= ' Utf-8 ')) B=CONN.RECV (1024) ret=str (b,encoding= ' Utf-8 ') print (r ET) 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) #登陆或注册验证 self.usr_file (usrname) #展示用户的详细目录信息, supports CD and ls command while True:a=c
ONN.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.di Rname (Os.path.dirname (__file__)) from config import settings def send_file (file_path): "Send file:p Aram File_n AME: FileName: return: ' Size=os.stat (file_path). St_size file_name=os.path.basename (File_path) obj.sendall (str (size) + ', ' +file_name,encoding= ' utf-8 ') #发送文件大小和文件名 ret=obj.recv (1024) #接收已经传了多少 r=str (ret,encoding= ' utf-8 ') if r== ' s ': #文件不存在, to start has_send=0 else: #文件存在 Has_send=int (R) with open (File_path, ' RB ') as F:f.seek (Has_sen
d) #定位到已经传到的位置 while Has_send<size:data=f.read (1024) obj.sendall (data) Has_send+=len (data) Sys.stdout.write (' \ R ') #清空文件内容 Time.sleep (0.2) sys.stdout.write (' Sent%s%%|%s '% (int (has_send/size*100), round (
HAS_SEND/SIZE*40) * Sys.stdout.flush () #强制刷出内存 print ("Upload \ n") def command (command_name): ' Execute command
:p Aram Command_name:: return: ' Obj.sendall (bytes (command_name,encoding= ' utf-8 ')) RET=OBJ.RECV (1024) #接收命令需要接收的次数 Obj.sendall (' Received count ', encoding= ' Utf-8 ') r=str (ret,encoding= ' utf-8 ') for I-in range (int (r)): #共需要接收int (R) Secondary RET=OBJ.RECV (1024) #等待客
Home sent R=str (ret,encoding= ' GBK ') print (r) def login (usrname,pwd): ' Login:p Aram Usrname: Username:p aram pwd: Password : return: Whether to login successfully ' Obj.sendall (bytes (usrname+ ', ' +pwd,encoding= ' Utf-8 ')) RET=OBJ.RECV (1024) r=str (ret,encoding= ' u Tf-8 ') if r== ' y ': return 1 Else:return 0 def regist (usrname,pwd): "' Registered:p Aram Usrname: Username:p Aram PWD: Password: return: Whether to register successfully ' Obj.sendall (bytes (usrname+ ', ' +pwd,encoding= ' Utf-8 ')) RET=OBJ.RECV (1024) r=str (Ret,enco ding= ' Utf-8 ') if r== ' y ': return 1 Else:return 0 def before (usrname,pwd): "' Select login or register, display user's detailed catalog information, support CD and LS Order: Return: ' A=input (' Please select 1. Login 2. Registered ') Obj.sendall (bytes (a,encoding= ' utf-8 ')) OBJ.RECV (1024) if a== ' 1 ': RE
T=login (USRNAME,PWD) If Ret:print (' login succeeded ') return 1 else:print (' Username or password error ') return 0 elif a== ' 2 ': ret=regist (USRNAME,PWD) If Ret:print (' registered success ') return 1 else:print (' username already exists ') return 0 def usr_file (u Srname): Obj.sendall (bytes (' Print user file path ', encoding= ' Utf-8 ')) RET=OBJ.RECV (1024) #等待客户端发送 r=str (ret,encoding= ' utf-8 ') p Rint (R) while True:a=input (' Input cd switch directory, ls view directory details, q exit: ') Obj.sendall (bytes (a,encoding= ' utf-8 ')) if a== ' Q ': Break ELSE:RET=OBJ.RECV (1024) #等待客户端发送 r=str (ret,encoding= ' utf-8 ') If Len (r) ==1: #判断是cd结果还 Is the result of LS (LS only a subdirectory can also print directly) print (R) else:li=r.split (', ') for I-li:print (i) #打印每 A subdirectory def main (usrname,pwd): RET=OBJ.RECV (1024) #等待客户端发送 r=str (ret,encoding= ' Utf-8 ') print (R) Result=before (USRN AME,PWD) #登陆或注册 if Result:usr_file (usrname) while True:a=input (' Please select 1. File 2. Execute command Q exit: ') Obj.sendall ( Bytes (str (a), encoding= ' uTf-8 ') ret=obj.recv (1024) #确认是否收到a r=str (ret,encoding= ' Utf-8 ') print (R) if a== ' 1 ': B=inpu T (' Please enter file path (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 command: ') comma nd (b) elif a== ' Q ': Break else:print (' input error ') Obj.close () if __name__ = = ' __main__ ': OB J=socket.socket () #创建客户端socket对象 obj.connect (' 127.0.0.1 ', 9999) usrname=input (' Enter username ') pwd=input (' Please enter password ') Main (U SRNAME,PWD)
Summarize
The above is the Python implementation can be a breakpoint and concurrent FTP program, the full content of the article introduced in detail, I hope to learn or use Python to bring some help.