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的Bottle框架中返回静态文件和JSON对象的方法
Apr 30 Python
Python中struct模块对字节流/二进制流的操作教程
Jan 21 Python
python实现各进制转换的总结大全
Jun 18 Python
Tornado协程在python2.7如何返回值(实现方法)
Jun 22 Python
python3.6连接MySQL和表的创建与删除实例代码
Dec 28 Python
Python实现学生成绩管理系统
Apr 05 Python
Python中optparser库用法实例详解
Jan 26 Python
Python 处理文件的几种方式
Aug 23 Python
Python实现钉钉订阅消息功能
Jan 14 Python
Python实现ATM系统
Feb 17 Python
Python接口开发实现步骤详解
Apr 26 Python
使用OpenCV获取图片连通域数量,并用不同颜色标记函
Jun 04 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
shopex中集成的站长统计功能的代码简单分析
2011/08/11 PHP
PHP转换文件夹下所有文件编码的实现代码
2013/06/06 PHP
PHP使用finfo_file()函数检测上传图片类型的实现方法
2017/04/18 PHP
thinkphp框架使用JWTtoken的方法详解
2019/10/10 PHP
ThinkPHP5分页paginate代码实例解析
2020/11/10 PHP
Javascript学习笔记1 数据类型
2010/01/11 Javascript
jquery 查找iframe父级页面元素的实现代码
2011/08/28 Javascript
Jquery多选下拉列表插件jquery multiselect功能介绍及使用
2013/05/24 Javascript
Angular表单验证实例详解
2016/10/20 Javascript
JS获取一个表单字段中多条数据并转化为json格式
2017/10/17 Javascript
深入理解Node内建模块和对象
2019/03/12 Javascript
tweenjs缓动算法的使用实例分析
2019/08/26 Javascript
解决vant中 tab栏遇到的坑 van-tabs
2020/11/04 Javascript
[01:00:44]DOTA2上海特级锦标赛主赛事日 - 3 败者组第三轮#1COL VS Alliance第三局
2016/03/04 DOTA
Python strip lstrip rstrip使用方法
2008/09/06 Python
Python常见字符串操作函数小结【split()、join()、strip()】
2018/02/02 Python
Python多线程原理与用法详解
2018/08/20 Python
python调用百度REST API实现语音识别
2018/08/30 Python
python广度优先搜索得到两点间最短路径
2019/01/17 Python
Django 模型类(models.py)的定义详解
2019/07/19 Python
PyTorch中permute的用法详解
2019/12/30 Python
Python多线程获取返回值代码实例
2020/02/17 Python
Python pip安装模块提示错误解决方案
2020/05/22 Python
pytorch中的weight-initilzation用法
2020/06/24 Python
python爬虫中的url下载器用法详解
2020/11/30 Python
新加坡时尚网上购物:Zalora新加坡
2016/07/26 全球购物
String这个类型的class为何定义成final?
2012/11/13 面试题
信息技术专业大学生个人的自我评价
2013/10/05 职场文书
财务会计专业毕业生自荐信
2013/10/19 职场文书
北京大学自荐信范文
2014/01/28 职场文书
过程装备与控制工程专业求职信
2014/07/02 职场文书
师德师风自查材料
2014/10/14 职场文书
2016幼儿园中班开学寄语
2015/12/03 职场文书
Python爬虫爬取全球疫情数据并存储到mysql数据库的步骤
2021/03/29 Python
解决python存数据库速度太慢的问题
2021/04/23 Python
详解gantt甘特图可拖拽、编辑(vue、react都可用 highcharts)
2021/11/27 Vue.js