socket file transfer and validation based on python3
- 2020-11-20 06:10:08
- OfStack
socket based file transfer and MD5 value verification, for your reference, the specific content is as follows
File transfer is divided into two classes, one for the server and one for the client.
The client initiates the request to send or receive the file, and the server receives or sends the file after receiving the request, and finally checks the value of MD5
socket data is packaged through the struct module
When the file needs to be sent to the server, the sendFile function is called. The struct package contains file information, file size, file MD5 and other information. The server performs MD5 value verification after receiving the file, and returns success after successful verification
When the file needs to be downloaded from the server, the recvFile function is called and the MD5 verification is performed after the file is received
The client class code is as follows
import socket
import struct,os
import subprocess
dataFormat='8s32s100s100sl'
class fileClient():
def __init__(self,addr):
self.addr = addr
self.action = ''
self.fileName = ''
self.md5sum = ''
self.clientfilePath = ''
self.serverfilePath = ''
self.size = 0
def struct_pack(self):
ret = struct.pack(dataFormat,self.action.encode(),self.md5sum.encode(),self.clientfilePath.encode(),
self.serverfilePath.encode(),self.size)
return ret
def struct_unpack(self,package):
self.action,self.md5sum,self.clientfilePath,self.serverfilePath,self.size = struct.unpack(dataFormat,package)
self.action = self.action.decode().strip('\x00')
self.md5sum = self.md5sum.decode().strip('\x00')
self.clientfilePath = self.clientfilePath.decode().strip('\x00')
self.serverfilePath = self.serverfilePath.decode().strip('\x00')
def sendFile(self,clientfile,serverfile):
if not os.path.exists(clientfile):
print(' The source file / Folder does not exist ')
return "No such file or directory"
self.action = 'upload'
(status, output) = subprocess.getstatusoutput("md5sum " + clientfile + " | awk '{printf $1}'")
if status == 0:
self.md5sum = output
else:
return "md5sum error:"+status
self.size = os.stat(clientfile).st_size
self.serverfilePath = serverfile
self.clientfilePath = clientfile
ret = self.struct_pack()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect(self.addr)
s.send(ret)
recv = s.recv(1024)
if recv.decode() == 'dirNotExist':
print(" The target file / Folder does not exist ")
return "No such file or directory"
elif recv.decode() == 'ok':
fo = open(clientfile, 'rb')
while True:
filedata = fo.read(1024)
if not filedata:
break
s.send(filedata)
fo.close()
recv = s.recv(1024)
if recv.decode() == 'ok':
print(" File transfer successful ")
s.close()
return 0
else:
s.close()
return "md5sum error:md5sum is not correct!"
except Exception as e:
print(e)
return "error:"+str(e)
def recvFile(self,clientfile,serverfile):
if not os.path.isdir(clientfile):
filePath,fileName = os.path.split(clientfile)
else:
filePath = clientfile
if not os.path.exists(filePath):
print(' Local object file / Folder does not exist ')
return "No such file or directory"
self.action = 'download'
self.clientfilePath = clientfile
self.serverfilePath = serverfile
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect(self.addr)
ret = self.struct_pack()
s.send(ret)
recv = s.recv(struct.calcsize(dataFormat))
self.struct_unpack(recv)
if self.action.startswith("ok"):
if os.path.isdir(clientfile):
fileName = (os.path.split(serverfile))[1]
clientfile = os.path.join(clientfile, fileName)
self.recvd_size = 0
file = open(clientfile, 'wb')
while not self.recvd_size == self.size:
if self.size - self.recvd_size > 1024:
rdata = s.recv(1024)
self.recvd_size += len(rdata)
else:
rdata = s.recv(self.size - self.recvd_size)
self.recvd_size = self.size
file.write(rdata)
file.close()
print('\n Wait for the check ...')
(status, output) = subprocess.getstatusoutput("md5sum " + clientfile + " | awk '{printf $1}'")
if output == self.md5sum:
print(" File transfer successful ")
else:
print(" File validation failed ")
(status, output) = subprocess.getstatusoutput("rm " + clientfile)
elif self.action.startswith("nofile"):
print(' Remote source file / Folder does not exist ')
return "No such file or directory"
except Exception as e:
print(e)
return "error:"+str(e)
The server class code is as follows
import socket
import struct,os
import subprocess
import socketserver
dataFormat='8s32s100s100sl'
class fileServer(socketserver.StreamRequestHandler):
def struct_pack(self):
ret = struct.pack(dataFormat, self.action.encode(), self.md5sum.encode(), self.clientfilePath.encode(),
self.serverfilePath.encode(), self.size)
return ret
def struct_unpack(self, package):
self.action, self.md5sum, self.clientfilePath, self.serverfilePath, self.size = struct.unpack(dataFormat,
package)
self.action = self.action.decode().strip('\x00')
self.md5sum = self.md5sum.decode().strip('\x00')
self.clientfilePath = self.clientfilePath.decode().strip('\x00')
self.serverfilePath = self.serverfilePath.decode().strip('\x00')
def handle(self):
print('connected from:', self.client_address)
fileinfo_size = struct.calcsize(dataFormat)
self.buf = self.request.recv(fileinfo_size)
if self.buf:
self.struct_unpack(self.buf)
print("get action:"+self.action)
if self.action.startswith("upload"):
try:
if os.path.isdir(self.serverfilePath):
fileName = (os.path.split(self.clientfilePath))[1]
self.serverfilePath = os.path.join(self.serverfilePath, fileName)
filePath,fileName = os.path.split(self.serverfilePath)
if not os.path.exists(filePath):
self.request.send(str.encode('dirNotExist'))
else:
self.request.send(str.encode('ok'))
recvd_size = 0
file = open(self.serverfilePath, 'wb')
while not recvd_size == self.size:
if self.size - recvd_size > 1024:
rdata = self.request.recv(1024)
recvd_size += len(rdata)
else:
rdata = self.request.recv(self.size - recvd_size)
recvd_size = self.size
file.write(rdata)
file.close()
(status, output) = subprocess.getstatusoutput("md5sum " + self.serverfilePath + " | awk '{printf $1}'")
if output == self.md5sum:
self.request.send(str.encode('ok'))
else:
self.request.send(str.encode('md5sum error'))
except Exception as e:
print(e)
finally:
self.request.close()
elif self.action.startswith("download"):
try:
if os.path.exists(self.serverfilePath):
(status, output) = subprocess.getstatusoutput("md5sum " + self.serverfilePath + " | awk '{printf $1}'")
if status == 0:
self.md5sum = output
self.action = 'ok'
self.size = os.stat(self.serverfilePath).st_size
ret = self.struct_pack()
self.request.send(ret)
fo = open(self.serverfilePath, 'rb')
while True:
filedata = fo.read(1024)
if not filedata:
break
self.request.send(filedata)
fo.close()
else:
self.action = 'nofile'
ret = self.struct_pack()
self.request.send(ret)
except Exception as e:
print(e)
finally:
self.request.close()
Call server and start the service
import fileSocket
import threading
import socketserver
import time
serverIp = '127.0.0.1'
serverPort = 19821
serverAddr = (serverIp,serverPort)
class fileServerth(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.create_time = time.time()
self.local = threading.local()
def run(self):
print("fileServer is running...")
fileserver.serve_forever()
fileserver = socketserver.ThreadingTCPServer(serverAddr, fileSocket.fileServer)
fileserverth = fileServerth()
fileserverth.start()
Call client to send/receive the file
import fileSocket
serverIp = '127.0.0.1'
serverPort = 19821
serverAddr = (serverIp,serverPort)
fileclient = fileSocket.fileClient(serverAddr)
fileclient.sendFile('fromClientPath/file','toServerPath/file')
fileclient.recvFile('toClientPath/file','fromServerPath/file')