python利用socketserver实现并发套接字功能


Posted in Python onJanuary 26, 2018

本文实现利用python的socketserver这个强大的模块实现套接字的并发,具体内容如下

目录结构如下:

python利用socketserver实现并发套接字功能

测试文件请放在server_file文件夹里面

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: PyCharm

import json
import time
import hashlib
import struct
import os
from socketserver import *

FILE_PATH = os.path.dirname(os.path.abspath(__file__))+'\\server_file'

class MYserver(BaseRequestHandler): # 设置一个类,基础BaseRequestHandler这个类
 def handle(self):     # 这个方法下添加通信功能(和上面创建类一样,这是socketserver的固定模式)
  print(self.client_address)
  '''
  :functions: 使用socketserver的并发套接字,提供客户端下载文件,并对文件进行MD5加密
  '''
  while True:
   try:
    data = self.request.recv(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')) # 这里发现小问题,不回复一个信息的话,发送给客户端的包头居然成了没有封装
     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())
         }
     # 包头信息序列化
     file_header_dump = json.dumps(file_header)
     # 编译成2进制
     file_header_bytes = file_header_dump.encode('gbk')
     # 封装报头
     file_header_struct = struct.pack('i',len(file_header_bytes))
     # 发送报头
     self.request.send(file_header_struct)
     # 发送报文内容
     self.request.send(file_header_bytes)
     # 发送文件数据
     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) # 这里后续可以拓展一个进度或者网速显示功能
   except Exception:
    self.request.close()


if __name__ == '__main__':
 server = ThreadingTCPServer(('127.0.0.1',8080),MYserver) # windows下只能开启多线程
 server.serve_forever()

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: PyCharm

from socket import *
import os,sys
import hashlib
import struct
import math
import json

FILE_PATH = os.path.dirname(os.path.abspath(__file__))+'\\client_file'


# 显示下载进度条功能,可以拓展为显示下载速度(提示,因为每次传输4096个字节,那么下载网速为KB/S,1KB个字节=1024B(字节),那么1s传输了多少个字节呢?)
def progress(recvd, total):
 fraction = '{:.0%}'.format(recvd / total)
 sys.stdout.write('\r[%-30s] %s' % ('#' * int(math.floor(recvd * 30 / total)), fraction))
 sys.stdout.flush()
 if recvd == total:
  sys.stdout.write('\n')


# 主函数
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.recv(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 = client.recv(4)
  if not header:break
  header_json_len = struct.unpack('i', header)[0]
  header_json_bytes = client.recv(header_json_len)
  header_josn = header_json_bytes.decode('gbk')
  header_dic = json.loads(header_josn)
  # 去除包头内容进行下载
  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')
  # 收到文件后,读取文件进行加密,看是否与服务端下载的文件一致!
  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('文件验证通过')
  else:
   print('文件损坏,删除文件')
   os.remove(FILE_PATH+r'\%s' %data_file)


if __name__ == '__main__':
 run('127.0.0.1',8080)

自己可以设置一个多用户登录,然后测试,用户下载同一个文件,分别存入每个用户自己的家目录下面,效果更好。

当然现在也能测试,开启两个客户端同时下载文件。

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

Python 相关文章推荐
在Python的while循环中使用else以及循环嵌套的用法
Oct 14 Python
详解python 模拟豆瓣登录(豆瓣6.0)
Apr 18 Python
python下的opencv画矩形和文字注释的实现方法
Jul 09 Python
Python3使用xml.dom.minidom和xml.etree模块儿解析xml文件封装函数的方法
Sep 23 Python
python实现计算器功能
Oct 31 Python
Django实现从数据库中获取到的数据转换为dict
Mar 27 Python
Python填充任意颜色,不同算法时间差异分析说明
May 16 Python
使用Django搭建网站实现商品分页功能
May 22 Python
浅谈Python 函数式编程
Jun 20 Python
如何通过命令行进入python
Jul 06 Python
Python实现自动装机功能案例分析
Oct 22 Python
基于Python的接口自动化unittest测试框架和ddt数据驱动详解
Jan 27 Python
Django的HttpRequest和HttpResponse对象详解
Jan 26 #Python
Python编程实现的简单神经网络算法示例
Jan 26 #Python
Django使用httpresponse返回用户头像实例代码
Jan 26 #Python
Django rest framework基本介绍与代码示例
Jan 26 #Python
Python实现PS图像调整之对比度调整功能示例
Jan 26 #Python
Python实现PS滤镜特效之扇形变换效果示例
Jan 26 #Python
修复CentOS7升级Python到3.6版本后yum不能正确使用的解决方法
Jan 26 #Python
You might like
php中取得URL的根域名的代码
2011/03/23 PHP
javascript动画之圆形运动,环绕鼠标运动作小球
2010/07/20 Javascript
iframe 上下滚动条如何默认在下方实现原理
2012/12/10 Javascript
js切换光标示例代码
2013/10/10 Javascript
基于jquery插件实现常见的幻灯片效果
2013/11/01 Javascript
JS图像无缝滚动脚本非常好用
2014/02/10 Javascript
JavaScript中的单引号和双引号报错的解决方法
2014/09/01 Javascript
JavaScript学习笔记之JS函数
2015/01/22 Javascript
JavaScript 动态加载脚本和样式的方法
2015/04/13 Javascript
javascript格式化日期时间方法汇总
2015/06/19 Javascript
jquery判断input值不为空的方法
2016/06/05 Javascript
JavaScript6 let 新语法优势介绍
2016/07/15 Javascript
JavaScript 事件流、事件处理程序及事件对象总结
2017/04/01 Javascript
微信小程序中form 表单提交和取值实例详解
2017/04/20 Javascript
ExtJs的Ext.Ajax.request实现waitMsg等待提示效果
2017/06/14 Javascript
解决JSON.stringify()自动将中文转译成unicode的问题
2018/01/05 Javascript
JS实现的全选、全不选及反选功能【案例】
2019/02/19 Javascript
JavaScript数据结构与算法之二叉树插入节点、生成二叉树示例
2019/02/21 Javascript
微信小程序 setData 对 data数据影响问题
2019/04/18 Javascript
node静态服务器实现静态读取文件或文件夹
2019/12/03 Javascript
VUE+elementui组件在table-cell单元格中绘制微型echarts图
2020/04/20 Javascript
python使用marshal模块序列化实例
2014/09/25 Python
深入探究Python中变量的拷贝和作用域问题
2015/05/05 Python
Python决策树分类算法学习
2017/12/22 Python
python实现SOM算法
2018/02/23 Python
Python高阶函数、常用内置函数用法实例分析
2019/12/26 Python
python实现连连看游戏
2020/02/14 Python
Python logging日志库空间不足问题解决
2020/09/14 Python
详解Python yaml模块
2020/09/23 Python
如何从一个文件档案的尾端新增记录
2016/12/02 面试题
土木工程建筑专业毕业生求职信
2013/10/21 职场文书
好的促销活动方案
2014/08/21 职场文书
交通事故协议书范本
2014/11/18 职场文书
2019年鼓励无偿献血倡议书
2019/09/17 职场文书
《家庭教育》读后感3篇
2019/12/18 职场文书
java调用Restful接口的三种方法
2021/08/23 Java/Android