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中的命令行参数解析工具之docopt详解
Mar 27 Python
Python处理命令行参数模块optpars用法实例分析
May 31 Python
Python基于xlrd模块操作Excel的方法示例
Jun 21 Python
Python 比较文本相似性的方法(difflib,Levenshtein)
Oct 15 Python
Python基本语法之运算符功能与用法详解
Oct 22 Python
python 列表、字典和集合的添加和删除操作
Dec 16 Python
python3爬取torrent种子链接实例
Jan 16 Python
python使用建议与技巧分享(二)
Aug 17 Python
python 基于opencv 绘制图像轮廓
Dec 11 Python
python里glob模块知识点总结
Jan 05 Python
详解Python中的Lock和Rlock
Jan 26 Python
matplotlib绘制正余弦曲线图的实现
Feb 22 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 smarty 二级分类代码和模版循环例子
2011/06/01 PHP
php 带逗号千位符数字的处理方法
2012/01/10 PHP
解析Ubuntu下crontab命令的用法
2013/06/24 PHP
浅析Dos下运行php.exe,出现没有找到php_mbstring.dll 错误的解决方法
2013/06/29 PHP
php下拉选项的批量操作的实现代码
2013/10/14 PHP
一组PHP可逆加密解密算法实例代码
2014/01/21 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十)
2014/06/24 PHP
PHP结合jQuery实现找回密码
2015/07/22 PHP
利用php输出不同的心形图案
2016/04/22 PHP
PHP检测数据类型的几种方法(总结)
2017/03/04 PHP
基于php数组中的索引数组和关联数组详解
2018/03/12 PHP
避免回车键导致的页面无意义刷新的解决方法
2011/04/12 Javascript
验证控件与Button的OnClientClick事件详细解析
2013/12/04 Javascript
JavaScript之AOP编程实例
2015/07/17 Javascript
基于jQuery实现的美观星级评论打分组件代码
2015/10/30 Javascript
JavaScript实现仿淘宝商品购买数量的增减效果
2016/01/22 Javascript
快速入门Vue
2016/12/19 Javascript
jQuery实现简单的抽奖游戏
2017/05/05 jQuery
AngularJS路由Ui-router模块用法示例
2017/05/29 Javascript
详解在WebStorm中添加Vue.js单文件组件的高亮及语法支持
2017/10/21 Javascript
node.js中express模块创建服务器和http模块客户端发请求
2019/03/06 Javascript
jQuery实现获取多选框的值示例
2020/02/07 jQuery
Javascript表单序列化原理及实现代码详解
2020/10/30 Javascript
[46:58]完美世界DOTA2联赛PWL S3 Forest vs LBZS 第一场 12.17
2020/12/19 DOTA
深入分析在Python模块顶层运行的代码引起的一个Bug
2014/07/04 Python
在Python中操作文件之truncate()方法的使用教程
2015/05/25 Python
Python脚本实时处理log文件的方法
2016/11/21 Python
django启动uwsgi报错的解决方法
2018/04/08 Python
详谈Numpy中数组重塑、合并与拆分方法
2018/04/17 Python
打印tensorflow恢复模型中所有变量与操作节点方式
2020/05/26 Python
国贸类专业毕业生的求职信分享
2013/12/08 职场文书
反四风个人对照检查材料
2014/09/26 职场文书
会计实训报告范文
2014/11/04 职场文书
先进个人事迹材料
2014/12/29 职场文书
2016年学校综治宣传月活动总结
2016/03/16 职场文书
解决Jenkins集成SonarQube遇到的报错问题
2021/07/15 Java/Android