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 相关文章推荐
Django1.3添加app提示模块不存在的解决方法
Aug 26 Python
Python中的异常处理学习笔记
Jan 28 Python
Python中每次处理一个字符的5种方法
May 21 Python
python requests post多层字典的方法
Dec 27 Python
django之使用celery-把耗时程序放到celery里面执行的方法
Jul 12 Python
python excel转换csv代码实例
Aug 26 Python
Python 进程操作之进程间通过队列共享数据,队列Queue简单示例
Oct 11 Python
Python批量启动多线程代码实例
Feb 18 Python
python 一维二维插值实例
Apr 22 Python
详解Python遍历列表时删除元素的正确做法
Jan 07 Python
python之基数排序的实现
Jul 26 Python
python3操作redis实现List列表实例
Aug 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
PHP 在线翻译函数代码
2009/05/07 PHP
PHP 中TP5 Request 请求对象的实例详解
2017/07/31 PHP
分享一个asp.net pager分页控件
2012/01/04 Javascript
jQuery中slideUp()方法用法分析
2014/12/24 Javascript
JS当前页面登录注册框,固定DIV,底层阴影的实例代码
2016/09/29 Javascript
vue使用stompjs实现mqtt消息推送通知
2017/06/22 Javascript
JavaScript实现body内任意节点的自定义属性功能示例
2017/09/18 Javascript
vue-cli+webpack项目 修改项目名称的方法
2018/02/28 Javascript
Vue开发之watch监听数组、对象、变量操作分析
2019/04/25 Javascript
JavaScript Array对象使用方法解析
2019/09/24 Javascript
vue+axios实现post文件下载
2019/09/25 Javascript
javascript使用Blob对象实现的下载文件操作示例
2020/04/18 Javascript
[56:18]DOTA2上海特级锦标赛主赛事日 - 4 败者组第四轮#2 MVP.Phx VS Fnatic第二局
2016/03/05 DOTA
[01:00:13]完美世界DOTA2联赛 LBZS vs Forest 第一场 11.07
2020/11/09 DOTA
Python序列化基础知识(json/pickle)
2017/10/19 Python
pandas string转dataframe的方法
2018/04/11 Python
python对象与json相互转换的方法
2019/05/07 Python
python对文件目录的操作方法实例总结
2019/06/24 Python
简单了解python协程的相关知识
2019/08/31 Python
Python面向对象魔法方法和单例模块代码实例
2020/03/25 Python
Django Admin设置应用程序及模型顺序方法详解
2020/04/01 Python
使用Python将Exception异常错误堆栈信息写入日志文件
2020/04/08 Python
matplotlib 对坐标的控制,加图例注释的操作
2020/04/17 Python
使用 prometheus python 库编写自定义指标的方法(完整代码)
2020/06/29 Python
五分钟带你搞懂python 迭代器与生成器
2020/08/30 Python
html5时钟实现代码
2010/10/22 HTML / CSS
HTML5中新标签和常用标签详解
2014/03/07 HTML / CSS
Watch Station官方网站:世界一流的手表和智能手表
2020/01/05 全球购物
师范学院毕业生求职信
2014/06/24 职场文书
感谢信的格式
2015/01/21 职场文书
幼儿园教师自我评价
2015/03/04 职场文书
2015最新婚礼司仪主持词
2015/06/30 职场文书
2016年领导干部正风肃纪心得体会
2015/10/09 职场文书
golang slice元素去重操作
2021/04/30 Golang
Redis Cluster集群动态扩容的实现
2021/07/15 Redis
html网页引入svg图片的4种方式
2022/08/05 HTML / CSS