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 __setattr__、 __getattr__、 __delattr__、__call__用法示例
Mar 06 Python
Python读取和处理文件后缀为.sqlite的数据文件(实例讲解)
Jun 27 Python
python的多重继承的理解
Aug 06 Python
用 Python 爬了爬自己的微信朋友(实例讲解)
Aug 25 Python
Python实现扣除个人税后的工资计算器示例
Mar 26 Python
python如何生成网页验证码
Jul 28 Python
将pandas.dataframe的数据写入到文件中的方法
Dec 07 Python
python for和else语句趣谈
Jul 02 Python
Django REST框架创建一个简单的Api实例讲解
Nov 05 Python
pytorch实现线性拟合方式
Jan 15 Python
python实现批量提取指定文件夹下同类型文件
Apr 05 Python
python中urllib包的网络请求教程
Apr 19 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 adodb连接不同数据库
2009/03/19 PHP
ThinkPHP使用心得分享-分页类Page的用法
2014/05/15 PHP
动态表单验证的操作方法和TP框架里面的ajax表单验证
2017/07/19 PHP
详解php命令注入攻击
2019/04/06 PHP
Js冒泡事件详解及阻止示例
2014/03/21 Javascript
第一次接触神奇的Bootstrap表单
2016/07/27 Javascript
js 获取本地文件及目录的方法(推荐)
2016/11/10 Javascript
实现点击下箭头变上箭头来回切换的两种方法【推荐】
2016/12/14 Javascript
JavaScript设计模式之代理模式详解
2017/06/09 Javascript
JavaScript 获取元素在父节点中的下标(推荐)
2017/06/28 Javascript
ExtJs整合Echarts的示例代码
2018/02/27 Javascript
js中document.write和document.writeln的区别
2018/03/11 Javascript
微信小程序 组件的外部样式externalClasses使用详解
2019/09/06 Javascript
Angular8 简单表单验证的实现示例
2020/06/03 Javascript
在Python中使用NLTK库实现对词干的提取的教程
2015/04/08 Python
flask框架配置mysql数据库操作详解
2019/11/29 Python
在tensorflow以及keras安装目录查询操作(windows下)
2020/06/19 Python
pytorch VGG11识别cifar10数据集(训练+预测单张输入图片操作)
2020/06/24 Python
PyQt5结合matplotlib绘图的实现示例
2020/09/15 Python
物业管理个人自我评价
2013/11/08 职场文书
高二化学教学反思
2014/01/30 职场文书
超市中秋节活动方案
2014/02/12 职场文书
乡镇办公室工作决心书
2014/03/11 职场文书
社团活动总结报告
2014/06/27 职场文书
部队反四风对照检查材料
2014/09/26 职场文书
三严三实民主生活会发言稿
2014/10/13 职场文书
2014年反腐倡廉工作总结
2014/12/05 职场文书
2015年度信用社工作总结
2015/05/04 职场文书
2015年乡镇工会工作总结
2015/05/19 职场文书
2015年安全生产月工作总结
2015/07/27 职场文书
幼儿园开学家长寄语(2016春季)
2015/12/03 职场文书
大学生入党自我鉴定范文
2019/06/21 职场文书
2019职场单身人才调研报告:互联网行业单身比例最高
2019/08/07 职场文书
redis哨兵常用命令和监控示例详解
2021/05/27 Redis
详细谈谈JavaScript中循环之间的差异
2021/08/23 Javascript
Apache Hudi数据布局黑科技降低一半查询时间
2022/03/31 Servers