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模块学习 filecmp 文件比较
Aug 27 Python
浅谈Django学习migrate和makemigrations的差别
Jan 18 Python
深入浅析Python获取对象信息的函数type()、isinstance()、dir()
Sep 17 Python
python的pytest框架之命令行参数详解(下)
Jun 27 Python
python 并发编程 非阻塞IO模型原理解析
Aug 20 Python
Python3运算符常见用法分析
Feb 14 Python
Python表达式的优先级详解
Feb 18 Python
使用Django清空数据库并重新生成
Apr 03 Python
python神经网络编程实现手写数字识别
May 27 Python
Python xpath表达式如何实现数据处理
Jun 13 Python
python读写数据读写csv文件(pandas用法)
Dec 14 Python
python pygame 愤怒的小鸟游戏示例代码
Feb 25 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
给多个地址发邮件的类
2006/10/09 PHP
php中文字母数字验证码实现代码
2008/04/25 PHP
php下目前为目最全的CURL中文说明
2010/08/01 PHP
php下网站防IP攻击代码,超级实用
2010/10/24 PHP
用js实现的自定义的对话框的实现代码
2010/03/21 Javascript
JavaScript 产生不重复的随机数三种实现思路
2012/12/13 Javascript
探讨javascript是不是面向对象的语言
2013/11/21 Javascript
javascript字母大小写转换的4个函数详解
2014/05/09 Javascript
javascript同步服务器时间和同步倒计时小技巧
2015/09/24 Javascript
谈一谈javascript闭包
2016/01/28 Javascript
jQuery轮播图效果精简版完整示例
2016/09/04 Javascript
如何快速上手Vuex
2017/02/14 Javascript
NodeJs模拟登陆正方教务
2017/04/28 NodeJs
基于nodejs+express4.X实现文件下载的实例代码
2017/07/13 NodeJs
JavaScript仿京东秒杀倒计时
2020/03/17 Javascript
[48:52]DOTA2上海特级锦标赛A组小组赛#2 Secret VS CDEC第一局
2016/02/25 DOTA
pymongo为mongodb数据库添加索引的方法
2015/05/11 Python
python检测是文件还是目录的方法
2015/07/03 Python
Windows上配置Emacs来开发Python及用Python扩展Emacs
2015/11/20 Python
详解python实现线程安全的单例模式
2018/03/05 Python
wxpython实现图书管理系统
2018/03/12 Python
python pycurl验证basic和digest认证的方法
2018/05/02 Python
pandas 根据列的值选取所有行的示例
2018/11/07 Python
Python基于scipy实现信号滤波功能
2019/05/08 Python
使用selenium模拟登录解决滑块验证问题的实现
2019/05/10 Python
分享PyCharm的几个使用技巧
2019/11/10 Python
Django获取model中的字段名和字段的verbose_name方式
2020/05/19 Python
Python使用struct处理二进制(pack和unpack用法)
2020/11/12 Python
使用HTML5拍照示例代码
2013/08/06 HTML / CSS
美国在线咖啡、茶和餐厅供应商:LollicupStore
2018/05/04 全球购物
一套Delphi的笔试题一
2016/02/14 面试题
战略合作协议书范本
2014/04/18 职场文书
新闻学专业职业生涯规划范文:我的人生我做主
2014/09/12 职场文书
初婚初育证明范本
2014/11/24 职场文书
小学班主任研修日志
2015/11/13 职场文书
JavaScript事件的委托(代理)的用法示例详解
2022/02/18 Javascript