Python uses socketserver to implement the concurrent socket function, pythonsocketserver
This article uses the powerful python socketserver module to implement socket concurrency.
The directory structure is as follows:
Put the test file in the server_file folder.
Server. py
#! /Usr/bin/env python #-*-coding: gbk-*-# @ Version: Python 3.5.2 # @ Time: 2018/1/24 10:29 # @ Author: Ncp # @ File: server. py # @ Software: PyCharmimport jsonimport timeimport hashlibimport structimport osfrom socketserver import * FILE_PATH = OS. path. dirname (OS. path. abspath (_ file _) + '\ server_file' class MYserver (BaseRequestHandler): # sets a class. The basic BaseRequestHandler class def handle (self ): # Add the communication function in this method (same as the class created above, which is the fixed mode of socketserver) print (self. client_address) ''': functions: uses the concurrent socket of socketserver, provides the client to download the file, and encrypts the file with MD5 ''' while True: try: data = self. request. recvs (1024) data_recv = data. decode ('gbk '). split () if not OS. path. exists (FILE_PATH + R' \ % s' % data_recv [1]): self. request. send ('file is not found '. encode ('gbk') continue else: data = self. request. send ('1 '. encode ('gbk') # the packet header sent to the client is not encapsulated with FILE_SIZE = OS. path. getsize (FILE_PATH + R' \ % s' % data_recv [1]) with open (FILE_PATH + R' \ % s' % data_recv [1], 'rb') as f: hash_file = f. read () m = hashlib. md5 () m. update (hash_file) m_hex = m. hexdigest () file_header = {'filename': data_recv [1], 'filesize': FILE_SIZE, 'md5': m_hex, 'time': time. strftime ('% Y-% m-% d-% x', time. localtime ()} # serialize the header information file_header_dump = json. dumps (file_header) # compiled into a binary file_header_bytes = file_header_dump.encode ('gbk') # encapsulated header file_header_struct = struct. pack ('I', len (file_header_bytes) # Send header self. request. send (file_header_struct) # send message content self. request. send (file_header_bytes) # send File data send_size = 0 with open (FILE_PATH + R' \ % s' % data_recv [1], 'rb') as f: for I in f: self. request. send (I) send_size + = len (I) # A progress or speed display function can be expanded later here except T Exception: self. request. close () if _ name _ = '_ main _': server = ThreadingTCPServer ('2017. 0.0.1 ', 8080), MYserver) # Only multi-thread server can be enabled in windows. serve_forever ()
View Code
Client. py
#! /Usr/bin/env python #-*-coding: gbk-*-# @ Version: Python 3.5.2 # @ Time: 2018/1/24 10:29 # @ Author: Ncp # @ File: client. py # @ Software: PyCharmfrom socket import * import OS, sysimport hashlibimport structimport mathimport jsonFILE_PATH = OS. path. dirname (OS. path. abspath (_ file _) + '\ client_file' # display the download progress bar function, which can be expanded to display the download speed (prompt, because 4096 bytes are transferred each time, so the download speed is KB/S, and the size of 1 KB is 1024B (bytes). How many bytes are transferred in 1 S ?) Def progress (recvd, total): fraction = '{:. 0% }'. format (recvd/total) sys. stdout. write ('\ r [%-30 s] % s' % (' # '* int (math. floor (recvd * 30/total), fraction) sys. stdout. flush () if recvd = total: sys. stdout. write ('\ n') # Main Function def run (ip, addr): client = socket (AF_INET, SOCK_STREAM) client. connect (ip, addr) while True: user_input = input ('> '). strip () cmd = user_input.split () if len (cmd )! = 2: print ('input format is error please use: get xx') continue if cmd [0] = 'get': client. send (user_input.encode ('gbk') data = client. recvs (1024) data_recv = data. decode ('gbk') if data_recv = 'file is not found': print (data_recv) continue else: print ('commands is not found') continue # header, then a series of processing headers = client. recv (4) if not header: break header_json_len = struct. unpack ('I', header) [0] header_js On_bytes = client. recv (header_json_len) header_josn = header_json_bytes.decode ('gbk') header_dic = json. loads (header_josn) # Remove the header content and download print (header_dic) data_len = header_dic ['filesize'] data_file = header_dic ['filename'] data_md5 = header_dic ['md5'] recv_size = 0 with open (FILE_PATH + R' \ % s' % data_file, 'wb ') as fw: while recv_size <data_len: recv_data = client. recv (4096) recv_size + = len (recv_data) Fw. write (recv_data) progress (recv_size, data_len) print ('Download completion, start validation ') # After receiving the file, read the file and encrypt it to see if it is consistent with the file downloaded by the server! With open (FILE_PATH + R' \ % s' % data_file, 'rb') as fr: data_total = fr. read () m = hashlib. md5 () m. update (data_total) m_hex = m. hexdigest () if m_hex = data_md5: print ('file verification passed ') else: print ('file corrupt, delete file') OS. remove (FILE_PATH + R' \ % s' % data_file) if _ name _ = '_ main _': run ('127. 0.0.1 ', 8080)
View Code
You can set up a multi-user login, and then test it. The user downloads the same file and saves it to each user's home directory, which is better.
You can also test it now. enable two clients to download files at the same time.