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(''.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利用socketserver实现并发套接字功能的更多相关文章
- 基于socketserver模块并发套接字
1.基于tcp协议 服务端: import socketserverclass MyHandler(socketserver .BaseRequestHandler ): def handle(sel ...
- Python 利用字典实现类似 java switch case 功能
def add(): print('add') def sub(): print('sub') def exit(): print('exit') choice = { '1' : add, '2' ...
- 利用Python中SocketServer 实现客户端与服务器间非阻塞通信
利用SocketServer模块来实现网络客户端与服务器并发连接非阻塞通信 版权声明 本文转自:http://blog.csdn.net/cnmilan/article/details/9664823 ...
- 进程池线程池 协程 gvent 单线程实现并发套接字
1.基于多线程实现套接字服务端支持并发 服务端 from socket import * from threading import Thread def comunicate(conn): whil ...
- 如何用Python统计《论语》中每个字的出现次数?10行代码搞定--用计算机学国学
编者按: 上学时听过山师王志民先生一场讲座,说每个人不论干什么,都应该学习国学(原谅我学了计算机专业)!王先生讲得很是吸引我这个工科男,可能比我的后来的那些同学听课还要认真些,当然一方面是兴趣.一方面 ...
- [Python] 利用Django进行Web开发系列(二)
1 编写第一个静态页面——Hello world页面 在上一篇博客<[Python] 利用Django进行Web开发系列(一)>中,我们创建了自己的目录mysite. Step1:创建视图 ...
- python利用or在列表解析中调用多个函数.py
python利用or在列表解析中调用多个函数.py """ python利用or在列表解析中调用多个函数.py 2016年3月15日 05:08:42 codegay & ...
- Python中利用函数装饰器实现备忘功能
Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下 " ...
- python 利用 ogr 写入shp文件,数据格式
python 利用 ogr 写入 shp 文件, 定义shp文件中的属性字段(field)的数据格式为: OFTInteger # 整型 OFTIntegerList # 整型list OFTReal ...
随机推荐
- Python的range函数详细用法
1. >>> range(1,5) #代表从1到5(不包含5) [1, 2, 3, 4]>>> 2. >>> range(1,5,2) #代表从 ...
- CSS实现商城分类导航效果(hover选择器)
学完制作出这个导航效果之后,收获最多的是了解了hover选择器的功能,:hover 选择器用于选择鼠标指针浮动在上面的元素.在鼠标移到元素上时向此元素添加特殊的样式(CSS).例如:改变鼠标悬停处的元 ...
- nvm 装 nodejs 重启终端失效的解决方法
(1) 安装 nvm wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.30.1/install.sh | bash (2) ...
- scrapy使用PhantomJS爬取数据
环境:python2.7+scrapy+selenium+PhantomJS 内容:测试scrapy+PhantomJS 爬去内容:涉及到js加载更多的页面 原理:配置文件打开中间件+修改proces ...
- angular4.0常用依赖汇总
Routes 路由配置 Router 路由跳转 ActivatedRoute 路由参数 FormsModule 表单配置(在app.module.ts中注入在imports下) EventEmitte ...
- html5 storage事件
HTML5 虽然很多年了,但是真的了解不不够不够.主题说的是 storage时间,说起对 storage 事件的了解还是从 QQ音乐 说起. QQ音乐的主页是 https://y.qq.com , 而 ...
- [原创]Nginx反向代理及负载均衡
1.基本命令 # 启动nginx start nginx.exe # windowsnginx -c /usr/local/nginx/conf/nginx.conf # Linux# 优雅的停止ng ...
- mvc接口、webapi、webservice 对比
最近做了很多项目,也同时使用了mvc的接口,webapi的接口,以及webservice 的接口.先两两对比如下: mvc和webapi区别: 1.MVC是建站的一种框架,倾向于返回用户的页面请求:a ...
- 【转载】OAuth2 流程
OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版. 本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为R ...
- C++拷贝构造函数(深拷贝与浅拷贝)
转自http://blog.csdn.net/lwbeyond/article/details/6202256/ 一. 什么是拷贝构造函数 对于普通类型的对象来说,它们之间的复制是很简单的,例如:in ...