python (大文件下载及进度条展示) 验证客户端链接的合法性,socketserver
##########总结###########
文件校验加进度条显示
####server
import os
import json
import socket
import struct
import hashlib sk = socket.socket()
sk.bind(('127.0.0.1', 9000))
sk.listen()
conn, addr = sk.accept()
filename = 'mysql-5.6.42-winx64.zip' # 文件名
absolute_path = os.path.join('D:\老男孩老师笔记\第二阶段共享', filename) # 文件绝对路径
buffer_size = 1024 * 1024 # 缓冲大小,这里表示1MB md5obj = hashlib.md5()
with open(absolute_path, 'rb') as f:
while True:
content = f.read(buffer_size) # 每次读取指定字节
if content:
md5obj.update(content)
else:
break # 当内容为空时,终止循环
md5 = md5obj.hexdigest()#打印出16进制的md5值
print(md5) # 打印md5值 dic = {'filename': filename,
'filename_md5': str(md5), 'buffer_size': buffer_size,
'filesize': os.path.getsize(absolute_path)}
str_dic = json.dumps(dic).encode('utf-8')
len_dic = len(str_dic)
length = struct.pack('i', len_dic)
conn.send(length) # dic的长度
conn.send(str_dic) # dic
with open(absolute_path, 'rb') as f: # 文件
while dic['filesize']:
content = f.read(dic['buffer_size'])
conn.send(content)
dic['filesize'] -= len(content)
'''
这里不能减等4096,因为文件,最后可能只有3字节。
要根据读取的长度len(content),来计算才是合理的。
'''
conn.close()
###############
1cb1926af121c5c1b52a1ec13314805b
####client
import json
import struct
import socket
import sys
import time
import hashlib
import os
def processBar(num, total): # 进度条 [接收大小,文件大小]
rate = num / total
rate_num = int(rate * 100)
if rate_num == 100:
r = '\r%s>%d%%\n' % ('=' * rate_num, rate_num,)
else:
r = '\r%s>%d%%' % ('=' * rate_num, rate_num,)
sys.stdout.write(r)
sys.stdout.flush start_time = time.time() # 开始时间
sk = socket.socket()
sk.connect(('127.0.0.1', 9000)) dic_len = sk.recv(4)
dic_len = struct.unpack('i', dic_len)[0]#查看长度
str_dic = sk.recv(dic_len).decode('utf-8')
dic = json.loads(str_dic) md5 = hashlib.md5()
with open(dic['filename'], 'wb') as f: # 使用wb更严谨一些,虽然可以使用ab
content_size = 0
while True:
content = sk.recv(dic['buffer_size']) # 接收指定大小
f.write(content) # 写入文件
content_size += len(content) # 接收大小
md5.update(content) # 摘要 processBar(content_size, dic['filesize']) # 执行进度条函数 [接收大小,文件大小]
if content_size == dic['filesize']: break # 当接收的等于文件大小时,终止循环 md5 = md5.hexdigest()
print(md5) # 打印md5值
if dic['filename_md5'] == str(md5):
print(('md5校验正确--下载成功'))
else:
print('文件验证失败')
os.remove(dic['filename']) # 删除文件
sk.close() # 关闭连接
end_time = time.time() # 结束时间
print('本次下载花费了{}秒'.format(end_time - start_time))
############
====================================================================================================>100%
1cb1926af121c5c1b52a1ec13314805b
md5校验正确--下载成功
本次下载花费了18.044031858444214秒
####验证合法性
使用hashlib.md5 加密
为什么要随机字符串,是为了防止客户端的数据被窃取
生成随机的bytes类型数据,它是解不出来的
import os
print(os.urandom(32))
执行输出:
b'PO\xca8\xc8\xf3\xa0\xb5,\xdd\xb8K \xa8D\x9cN"\x82\x03\x86g\x18e\xa7\x97\xa77\xb9\xa5VA'
###server
import os
import socket
import hashlib secret_key = '老衲洗头用飘柔' # 加密key sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.listen()
while True:
try:
conn,addr = sk.accept()
random_bytes = os.urandom(32) # 随即产生32个字节的字符串,返回bytes
conn.send(random_bytes) # 发送随机加密key
md5 = hashlib.md5(secret_key.encode('utf-8')) # 使用secret_key作为加密盐
md5.update(random_bytes) #得到MD5消息摘要
ret = md5.hexdigest() #以16进制返回消息摘要,它是一个32位长度的字符串
msg = conn.recv(1024).decode('utf-8') # 接收的信息解码
if msg == ret:print('是合法的客户端') # 如果接收的摘要和本机计算的摘要一致,就说明是合法的
else:conn.close() # 关闭连接
finally: # 无论如何,都执行下面的代码
sk.close() # 关闭连接
break
###client
import socket
import hashlib
secret_key = '老衲洗头用飘柔' # 加密key
sk = socket.socket()
sk.connect(('127.0.0.1',9000)) urandom = sk.recv(32) # 接收32字节,也就是os.urandom的返回值
md5_obj = hashlib.md5(secret_key.encode('utf-8')) # 使用加密盐加密
md5_obj.update(urandom)
sk.send(md5_obj.hexdigest().encode('utf-8')) # 发送md5摘要
print('-----')
sk.close() # 关闭连接
先执行server.py,再执行client.py
client输出:-----
server输出:是合法的客户端
socketserver
SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进 程” 专门负责处理当前客户端的所有请求。
它能实现多个客户端,同时连接,它继承了socket
####server
import socketserver
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
print(self.request)
self.request.send(b'hello') # 跟所有的client打招呼
print(self.request.recv(1024)) # 接收客户端的信息 server = socketserver.ThreadingTCPServer(('127.0.0.1',9000),MyServer)
server.serve_forever()
#######client
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9000))
print(sk.recv(1024))
inp = input('>>>').encode('utf-8')
sk.send(inp)
sk.close()
client输出:
b'hello'
>>>hi
server输出:
<socket.socket fd=316, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 49176)>
b'hi'
开多个客户端,也可以执行
########自己写一个socketserver
###server
import socket
from threading import Thread
class MySocket:
#init方法,将ip和端口封装到了self里面,并且实例化了一个socket对象
def __init__(self,server_addr): self.server_addr = server_addr
self.socket = socket.socket() #绑定了ip地址和端口,监听,执行了建立连接的方法
def serve_forever(self):
self.socket.bind(self.server_addr)
self.socket.listen(5)
self.build_connect()
#建立连接,将建立连接的过程循环起来,因为我们每次建立连接都需要开一个线程带走这个连接,去通过这个连接收发消息.
def build_connect(self): while 1:
#让主线程代码循环起来,要让accept方法和handle方法要异步起来,不然建立连接的这个循环无法循环起来,因为进入handle之后就出不来了,异步你会想到什么,并发,多进程或者多线程,多进程不合适,所以用多线程,每一个conn,一个线程
conn,addr = self.socket.accept()
# self.handle(conn)
#开线程处理conn,一个线程一个conn,
t = Thread(target=self.handle,args=(conn,))
t.start()
#收发消息的内容,每个线程都需要执行一下handle方法,将conn作为参数传给handle方法
def handle(self,conn):
while 1:
from_client_msg = conn.recv(1024).decode('utf-8')
print('来自客户的消息>>>>',from_client_msg) to_client_msg = input('宝宝说>>>>')
conn.send(to_client_msg.encode('utf-8')) if __name__ == '__main__':
ip_port = ('127.0.0.1',8001)
server = MySocket(ip_port)
server.serve_forever()
###client 可实现多个客户端 同时和一个server应对
import socket
client = socket.socket()
client.connect(('127.0.0.1',8001))
while 1:
to_server_msg = input('给宝宝的消息>>>')
client.send(to_server_msg.encode('utf-8')) from_server_msg = client.recv(1024).decode('utf-8')
print('来自宝宝的消息:',from_server_msg)
python (大文件下载及进度条展示) 验证客户端链接的合法性,socketserver的更多相关文章
- python 全栈开发,Day36(作业讲解(大文件下载以及进度条展示),socket的更多方法介绍,验证客户端链接的合法性hmac,socketserver)
先来回顾一下昨天的内容 黏包现象粘包现象的成因 : tcp协议的特点 面向流的 为了保证可靠传输 所以有很多优化的机制 无边界 所有在连接建立的基础上传递的数据之间没有界限 收发消息很有可能不完全相 ...
- 036_python的大文件下载以及进度条展示
复习 1.黏包现象 粘包现象的成因: tcp协议的特点,面向流的,为了保证可靠传输,所以有很多优化的机制. 无边界 所有在连接建立的基础上传递的数据之间没有界限. 收发消息很有可能不完全相等. 缓存机 ...
- Python之socketserver模块和验证客户端链接的合法性
验证客户端链接的合法性 分布式系统中实现一个简单的客户端链接认证功能 #_*_coding:utf-8_*_ from socket import * import hmac,os secret_ke ...
- python:验证客户端链接的合法性与socketserver
一.验证客户端链接的合法性 from socket import * import hmac,os secret_key=b'linhaifeng bang bang bang' def conn_a ...
- python网络编程之验证客户端链接的合法性
六.socket的更多方法介绍 服务端套接字函数s.bind() 绑定(主机,端口号)到套接字s.listen() 开始TCP监听s.accept() b被动接收TCP客户的连接,(阻塞式)等待连接的 ...
- socketv 验证客户端链接的合法性,socketserver
补充: send()与sendall() 在python socket编程中,有两个发送TCP的函数,send()与sendall(),区别如下: socket.send(string[, flags ...
- socketv 验证客户端链接的合法性
一 .socketv 验证客户端链接的合法性 send()与sendall() 验证客户端 加密验证 如果你想在分布式系统中实现一个简单的客户端链接认证功能,又不像SSL那么复杂,那么利用hmac+加 ...
- 一个简单、易用的Python命令行(terminal)进度条库
eprogress 是一个简单.易用的基于Python3的命令行(terminal)进度条库,可以自由选择使用单行显示.多行显示进度条或转圈加载方式,也可以混合使用. 示例 单行进度条 多行进度条 圆 ...
- Asp.Net上传大文件带进度条swfupload
Asp.Net基于swfupload上传大文件带进度条百分比显示,漂亮大气上档次,大文件无压力,先看效果 一.上传效果图 1.上传前界面:图片不喜欢可以自己换 2.上传中界面:百分比显示 3.上传后返 ...
随机推荐
- BZOJ2176Strange string——最小表示法
题目描述 给定一个字符串S = {S1, S2, S3 … Sn}, 如果在串SS中, 子串T(|T| = n)为所有长度为n的SS的字串中最小的(字符串的比较), 则称T为”奇怪的字串”. 你的任务 ...
- kibana get 查询失效
kibana版本:5.4 在使用kibana 查询数据时,如果我们根据数据id 来获得一条数据,写法 get 索引名称/类型名称/文档主键 如:get testindex/testtype/01 这样 ...
- Scrapy爬取伯乐在线文章
首先搭建虚拟环境,创建工程 scrapy startproject ArticleSpider cd ArticleSpider scrapy genspider jobbole blog.jobbo ...
- robotframework基本语法一
*** Settings *** Library OperatingSystem #Settings:导入测试库,资源文件,变量文件,为创建测试套件和test cases定义元数据 *** Varia ...
- Linux 检查端口gps命令
由于是游戏业务,环境主要是Nginx+Tomcat+Java Program gps脚本环境以及效果图如下: #!/bin/bash function Printf (){ == ];then pri ...
- Android undefined intent constructor错误?
本文选自StackOverflow(简称:SOF)精选问答汇总系列文章之一,本系列文章将为读者分享国外最优质的精彩问与答,供读者学习和了解国外最新技术.在Android中启动Service时出现&qu ...
- 【BZOJ2823】[AHOI2012]信号塔(最小圆覆盖)
[BZOJ2823][AHOI2012]信号塔(最小圆覆盖) 题面 BZOJ 洛谷 相同的题: BZOJ1 BZOJ2 洛谷 题解 模板题... #include<iostream> #i ...
- 【BZOJ5416】【NOI2018】冒泡排序(动态规划)
[BZOJ5416][NOI2018]冒泡排序(动态规划) 题面 BZOJ 洛谷 UOJ 题解 考场推出了就是两个上升子序列,并且最长下降子序列长度不超过\(2\)...然后大力暴力状压\(dp\)混 ...
- CDQ分治与整体二分学习笔记
CDQ分治部分 CDQ分治是用分治的方法解决一系列类似偏序问题的分治方法,一般可以用KD-tree.树套树或权值线段树代替. 三维偏序,是一种类似LIS的东西,但是LIS的关键字只有两个,数组下标和 ...
- 洛谷P2468 SDOI 2010 粟粟的书架
题意:给你一个矩形书架,每个点是这本书的页数,每次询问(x1,y1)(x2,y2)这个小矩形里最少需要取几本书使得页数和等于Hi. 题解:小数据二位前缀和预处理+二分答案,大数据一行所以用主席树做,感 ...