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.上传后返 ...
随机推荐
- 初步了解HTML
超文本标记语言(英语:HyperText Markup Language,简称:HTML)是一种用于创建网页的标准标记语言. 您可以使用 HTML 来建立自己的 WEB 站点,HTML 运行在浏览器上 ...
- 大学实验3指导:利用单链表实现A-B
实验目的:深入理解单链表的建立及操作 实验内容: 1.建立单链表A与B 2.实现主要的函数,查找.插入.删除等 3.实现操作A-B 步骤1:包含必要的函数库,对结构体LNode中的抽象数据类型Elem ...
- BZOJ 1912 巡逻(算竞进阶习题)
树的直径 这题如果k=1很简单,就是在树的最长链上加个环,这样就最大化的减少重复的路程 但是k=2的时候需要考虑两个环的重叠部分,如果没有重叠部分,则和k=1的情况是一样的,但是假如有重叠部分,我们可 ...
- linux tar 解压命令
如果提示 common not find 先进行安装如下 wget http://www.rarsoft.com/rar/rarlinux-5.3.0.tar.gz tar -zxvf rarlinu ...
- Android 可展开列表组件 ExpandableListView
ExpandableListView 是ListView的子类,它把应用中的列表项分为几组,每组里可包含多个列表项. 所显示的列表项应该由ExpandableListAdapter 接口提供,实现Ex ...
- 【BZOJ5324】[JXOI2018]守卫(动态规划)
[BZOJ5324][JXOI2018]守卫(动态规划) 题面 BZOJ 洛谷 题解 既然只能看到横坐标在左侧的点,那么对于任意一个区间\([l,r]\)而言,\(r\)必须被选. 假设\(r\)看不 ...
- for循环是怎么工作的
for...in 是Python程序员使用最多的语句,for 循环用于迭代容器对象中的元素,这些对象可以是列表.元组.字典.集合.文件,甚至可以是自定义类或者函数,例如: 作用于列表 >> ...
- User Agent 用户代理
User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本.CPU 类型.浏览器及版本.浏览器渲染引擎.浏览器语言.浏览器插件等. User A ...
- Java面试题-基础知识
参考文章:Java面试题-基础知识 基础能力 什么是值传递和引用传递 线程状态有哪些,它们之间是如何转换的 进程与线程的区别,进程间如何通讯,线程间如何通讯? HashMap的数据结构是什么?如何实现 ...
- poj1958 strange towers of hanoi
说是递推,其实也算是个DP吧. 就是4塔的汉诺塔问题. 考虑三塔:先从a挪n-1个到b,把最大的挪到c,然后再把n-1个从b挪到c,所以是 f[i] = 2 * f[i-1] + 1; 那么4塔类似: ...