基于python3实现socket文件传输和校验


Posted in Python onJuly 28, 2018

基于socket的文件传输并进行MD5值校验,供大家参考,具体内容如下

文件传输分为两个类,一个是服务端,一个是客户端。

客户端发起发送文件或接收文件的请求,服务端收到请求后接收或发送文件,最后进行MD5值的校验

socket数据通过struct模块打包

需要发送文件到服务端时,调用sendFile函数,struct包内包含文件信息、文件大小、文件MD5等信息,服务端接收到文件后进行MD5值校验,校验成功后则返回成功

需要从服务器下载文件时,调用recvFile函数,收到文件后进行MD5校验

client类代码如下

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('源文件/文件夹不存在')
   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("目标文件/文件夹不存在")
    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("文件传输成功")
     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('本地目标文件/文件夹不存在')
   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等待校验...')
    (status, output) = subprocess.getstatusoutput("md5sum " + clientfile + " | awk '{printf $1}'")
    if output == self.md5sum:
     print("文件传输成功")
    else:
     print("文件校验不通过")
     (status, output) = subprocess.getstatusoutput("rm " + clientfile)
   elif self.action.startswith("nofile"):
    print('远程源文件/文件夹不存在')
    return "No such file or directory"
  except Exception as e:
   print(e)
   return "error:"+str(e)

server类代码如下

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()

调用server,并开启服务

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()

调用client,发送/接受文件

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')

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中的日期时间处理详解
Nov 17 Python
python thrift搭建服务端和客户端测试程序
Jan 17 Python
简单实现python数独游戏
Mar 30 Python
python爬虫超时的处理的实例
Dec 19 Python
Python动态语言与鸭子类型详解
Jul 01 Python
python之pexpect实现自动交互的例子
Jul 25 Python
python爬虫中多线程的使用详解
Sep 23 Python
python编程进阶之异常处理用法实例分析
Feb 21 Python
Python json模块与jsonpath模块区别详解
Mar 05 Python
Python 远程开关机的方法
Nov 18 Python
Python利用socket模块开发简单的端口扫描工具的实现
Jan 27 Python
python 算法题——快乐数的多种解法
May 27 Python
python多进程实现文件下载传输功能
Jul 28 #Python
python如何生成网页验证码
Jul 28 #Python
python3利用tcp实现文件夹远程传输
Jul 28 #Python
python使用tornado实现简单爬虫
Jul 28 #Python
python编写简易聊天室实现局域网内聊天功能
Jul 28 #Python
对tensorflow 的模型保存和调用实例讲解
Jul 28 #Python
Python Socket编程之多线程聊天室
Jul 28 #Python
You might like
JpGraph php柱状图使用介绍
2011/08/23 PHP
浅析51个PHP处理字符串的函数
2013/08/02 PHP
php pdo oracle中文乱码的快速解决方法
2016/05/16 PHP
浅析php静态方法与非静态方法的用法区别
2016/05/17 PHP
php微信支付之公众号支付功能
2018/05/30 PHP
利用Dojo和JSON建立无限级AJAX动态加载的功能模块树
2007/03/24 Javascript
简单的jquery拖拽排序效果实现代码
2011/09/20 Javascript
在JavaScript中对HTML进行反转义详解
2016/05/18 Javascript
有关jQuery中parent()和siblings()的小问题
2016/06/01 Javascript
js css实现垂直方向自适应的三角提示菜单
2016/06/26 Javascript
JS中位置与大小的获取方法
2016/11/22 Javascript
bootstrap是什么_动力节点Java学院整理
2017/07/14 Javascript
详谈表单重复提交的三种情况及解决方法
2017/08/16 Javascript
jQuery实现动态添加节点与遍历节点功能示例
2017/11/09 jQuery
微信小程序倒计时功能实现代码
2017/11/09 Javascript
javascript实现Emrips反质数枚举的示例代码
2017/12/06 Javascript
jQuery中的类名选择器(.class)用法简单示例
2018/05/14 jQuery
JavaScript剩余操作符Rest Operator详解
2019/07/20 Javascript
javascript事件监听与事件委托实例详解
2019/08/16 Javascript
vue开发简单上传图片功能
2020/06/30 Javascript
在vue中对数组值变化的监听与重新响应渲染操作
2020/07/17 Javascript
python smtplib模块发送SSL/TLS安全邮件实例
2015/04/08 Python
python实现下载整个ftp目录的方法
2017/01/17 Python
Python学习笔记之if语句的使用示例
2017/10/23 Python
python通过tcp发送xml报文的方法
2018/12/28 Python
10个示例带你掌握python中的元组
2020/11/23 Python
捷科时代的软件测试笔试题
2015/11/09 面试题
装饰活动策划方案
2014/02/11 职场文书
劲霸男装广告词改编版
2014/03/21 职场文书
保密承诺书
2014/03/27 职场文书
2014社区三八妇女节活动方案
2014/03/30 职场文书
我的画教学反思
2014/04/28 职场文书
给老婆的道歉信
2015/01/20 职场文书
义诊活动总结
2015/02/04 职场文书
学生会辞职信
2015/03/02 职场文书
2015年骨干教师工作总结
2015/05/26 职场文书