一.POOL
Pool就是为了多线程访问数据库,减少数据库压力
回顾pymysql
import pymysql #建立连接 mysql_conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", password="", charset="utf8", db="day115") #创建游标 c = mysql_conn.cursor(cursor=pymysql.cursors.DictCursor) sql = "select * from users WHERE name='jwb' and age=73 " # 光标执行sql # res为生成几行 res = c.execute(sql) #获取结果 print(c.fetchall()) c.close() mysql_conn.close()
创建POOL
import pymysql from DBUtils.PooledDB import PooledDB POOL = PooledDB( creator=pymysql, # 使用链接数据库的模块 maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制连接数 mincached=2, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建 maxcached=5, # 链接池中最多闲置的链接,0和None不限制 maxshared=3, # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。 blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错 maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制 setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."] ping=0, # ping MySQL服务端,检查是否服务可用。 # 如:0 = None = never, # 1 = default = whenever it is requested, # 2 = when a cursor is created, # 4 = when a query is executed, # 7 = always host="127.0.0.1", port=3306, user="root", password="", charset="utf8", db="day115" ) # # conn = POOL.connection() # pymysql - conn # cur = conn.cursor(cursor=pymysql.cursors.DictCursor) # # sql = "select * from users WHERE name='jwb' and age=73 " # # res = cur.execute(sql) # # # print(cur.fetchall()) # # conn.close()
执行线程池
from dbpool import POOL import pymysql def create_conn(): conn = POOL.connection() cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) return conn,cursor def close_conn(conn,cursor): cursor.close() conn.close() def insert(sql,args): conn,cursor = create_conn() res = cursor.execute(sql,args) conn.commit() close_conn(conn,cursor) return res def fetch_one(sql,args): conn,cursor = create_conn() cursor.execute(sql,args) res = cursor.fetchone() close_conn(conn,cursor) return res def fetch_all(sql,args): conn,cursor = create_conn() cursor.execute(sql,args) res = cursor.fetchall() close_conn(conn,cursor) return res # sql = "insert into users(name,age) VALUES (%s, %s)" # insert(sql,("mjj",9)) sql = "select * from users where name=%s and age=%s" print(fetch_one(sql,("mjj",9)))
二.socket握手
就是在客户端请求头中获取Sec-WebSocket-Key与宝藏magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'进行匹配
当与客户端验证成功后就已经进行了握手
import socket, base64, hashlib sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(('127.0.0.1', 9527)) sock.listen(5) # 获取客户端socket对象 conn, address = sock.accept() # 获取客户端的【握手】信息 data = conn.recv(1024) print(data) """ GET /ws HTTP/1.1\r\n Host: 127.0.0.1:9527\r\n Connection: Upgrade\r\n Pragma: no-cache\r\n Cache-Control: no-cache\r\n User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36\r\n Upgrade: websocket\r\n Origin: http://localhost:63342\r\n Sec-WebSocket-Version: 13\r\n Accept-Encoding: gzip, deflate, br\r\n Accept-Language: zh-CN,zh;q=0.9\r\n Cookie: session=a6f96c20-c59e-4f33-84d9-c664a2f29dfc\r\n Sec-WebSocket-Key: MAZZU5DPIxWmhk/UWL2+BA==\r\n #这个就是那把钥匙 Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n """ # 以下动作是有websockethandler完成的 # magic string为:258EAFA5-E914-47DA-95CA-C5AB0DC85B11 def get_headers(data): #在获取的data列表中通过分割获取Sec-WebSocket-Key header_dict = {} header_str = data.decode("utf8") for i in header_str.split("\r\n"): if str(i).startswith("Sec-WebSocket-Key"): header_dict["Sec-WebSocket-Key"] = i.split(":")[1].strip() return header_dict headers = get_headers(data) # 提取请求头信息 # magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' #Sec-WebSocket-Key: MAZZU5DPIxWmhk/UWL2+BA== value = headers['Sec-WebSocket-Key'] + magic_string print(value) #将钥匙Sec-WebSocket-Key和宝藏magic_string进行加密 ac = base64.b64encode(hashlib.sha1(value.encode('utf-8')).digest()) # 对请求头中的sec-websocket-key进行加密 response_tpl = "HTTP/1.1 101 Switching Protocols\r\n" \ "Upgrade:websocket\r\n" \ "Connection: Upgrade\r\n" \ "Sec-WebSocket-Accept: %s\r\n" \ "WebSocket-Location: ws://127.0.0.1:9527\r\n\r\n" print(ac.decode('utf-8')) response_str = response_tpl % (ac.decode('utf-8')) # 响应【握手】信息 conn.send(response_str.encode("utf8")) # while True: msg = conn.recv(8096) print(msg)
需要在前端中访问
"zh-CN"> "UTF-8">Title "viewport" content="width=device-width, initial-scale=1">
发现,在前端发送的数据vm.send("abc)发到后端的数据是加密的,需要进行解密
解密方法
比如发送到服务端的是
b'\x81\x83H\xc0x\xa6y\xf2K'
第一个为统一的的\x81,用它的后一位与127求^,结果分三种 小于等于125,126,127
然后根据后面的数据长度/密码/数据/进行解密
#b'\x81\x89\xf3\x99\x81-\x15\x05\x01\xcbO\x1be\x97]' #b'\x81\x85s\x92a\x10\x1b\xf7\r|\x1c' #b'\x81\x83H\xc0x\xa6y\xf2K' hashstr = b'\x81\x85s\x92a\x10\x1b\xf7\r|\x1c' # b'\x81 \x85s \x92a\x10\x1b\xf7 \r|\x1c' <126 # \x85s = 5 hashstr = b'\x81\xfe\x02\xdc\x8d\xe8-\xb2hm\xa5W5u\xc8:\x16\x0c\x95(kt\x87W\x00b\xc52\x01\x0c\x95\x1fdi\xbeW9A\xcb\x1c\x0f\x07\x91>iS\xa7W)A\xc9\n\x06\x0c\x95;h`\xab]1d\xca)\x07\r\x9a,j~\x9fW1b\xc2\x0e\x01\x0e\x80\x16eG\xb7W\x00Y\xcb2(\r\x80*iR\x8cV4c\xca\x15\x06\x0c\x94-nh\xafU\t^\xc9\x0c\x00\r\xa0\x19iQ\xa6Z\nK\xc9\n\x00\x0e\xaa:iR\xa3W\x0bm\xc2\x0e\x01\r\x92\x12hW\xbaV4c\xc8\x11&\r\x92*eR\x86V7f\xc8\x16\x1b\x00\xad7bT\xa1U\x16~\xc5\r0\r\xa8:hP\xb0V4c\xcb\x1c\x07\x01\xac5bT\xa1T!Z\xcb8(\x0c\x949iR\xa3[\x14s\xc9\n\x06\x0c\x94-nh\xafZ"r\xc8\x1c\x11\r\x912hT\x8dW\x11K\xc8"!\x07\x91>iS\x88W\x08a\xc87\x05\r\x95/di\xbaW3_\xc2\x0e\x01\x0e\xac\x10hT\xb5W2\x7f\xc8\x11&\x0c\x949kX\xb9]1d\xc9\n\x00\r\x83.hN\xa9Z\nB\xc5=?\x00\xbb6bT\xa1W1}\xc8$6\r\x89\x03iQ\xa4]1d\xc9\t(\r\x8c,hW\x8dZ=g\xc9\x0b\x06\x00\x9a\x1diQ\xb2Q\rj\xc8\x1c&\x0c\x95\x1fhR\xb1V5E\xc2\x0e\x01\x0c\x92\x03iP\x97V5h\xc9\x0f\x1e\x07\x91>dq\xb2U0r\xc55*\r\xbd\x14bT\xa1V5e\xc8\x1c\x11\r\x910hx\xa1Q\rj\xc59(\x0e\xb1;iU\xb1W(P\xca8"\x0f\x8a#hg\xa7V5R\xc8\r-\r\xbb6eh\xa8]1d\xc8\x1c\x11\x0c\x96*kt\xa4W\x02P\xc5\x1c7\r\xa8\x04h`\xbcZ8g\xc2\x0e\x01\x0c\x96\x17kp\x80[\x14s\xc9\n\x06\r\x94\x01kp\xa3V4c\xca"\x0b\x07\x91>iP\xa0W#t\xc83\x02\x0f\x8a3bT\xa1V0W\xc84\x08\r\x89$hT\xafT>}\xc9\x0b\x12\x0b\xad0iV\xa0V5E\xce2\x0c\x0c\x93?dk\xa3[\x0eE\xcb&5\x0c\x949nh\xacZ9Q\xca\x17\x03\x0b\xad3ey\x8eW\x08i\xca\x1f\x04\x07\x91>kE\x89U\x17n\xc5;"\r\x83,bT\xa1W2\x7f\xc5+\x1c\r\x92\x12jR\x82]1d\xcb*"\x0c\x96\x17hm\xa5W5u\xca\x1c\r\x0e\xa6&iS\x88[\x0c\x7f\xc4+\x16\x0c\x959nh\xafT\tr\xc9\t(\x0c\x95\x08hF\x86V5E\xc9\x0b\x06\x0c\x979bT\xa1V7c\xcb%-\r\x89\x15hX\xa2]1d\xcb0\x04\x0c\x96\x17hz\x85V4c\xc2\x0e\x01\x0f\xa9\x04hx\xa3T\x1bU\xc5\x13\x01\x07\x91>hW\xa8Z\x0eU\xc5\x11%\x00\x8c\x17dp\xb4T1g\xc2\x0e\x01\x0e\xb1;ka\xadW4W\xca)\x07\x0b\xad0' # print(chushibiao[1],chushibiao[1]&127) # print(chushibiao[2:4],chushibiao[4:8]) # 将第二个字节也就是 \x83 第9-16位 进行与127进行位运算 payload = hashstr[1] & 127 print(payload) if payload == 127: extend_payload_len = hashstr[2:10] mask = hashstr[10:14] decoded = hashstr[14:] # 当位运算结果等于127时,则第3-10个字节为数据长度 # 第11-14字节为mask 解密所需字符串 # 则数据为第15字节至结尾 if payload == 126: extend_payload_len = hashstr[2:4] mask = hashstr[4:8] decoded = hashstr[8:] # 当位运算结果等于126时,则第3-4个字节为数据长度 # 第5-8字节为mask 解密所需字符串 # 则数据为第9字节至结尾 if payload <= 125: extend_payload_len = None mask = hashstr[2:6] decoded = hashstr[6:] # 当位运算结果小于等于125时,则这个数字就是数据的长度 # 第3-6字节为mask 解密所需字符串 # 则数据为第7字节至结尾 str_byte = bytearray() # b'\x81 \x85s \x92a\x10\x1b \xf7\r|\x1c' <126 for i in range(len(decoded)): # 0 \xf7 ^ \x92a 1 \r ^ \x10 \x1c ^ \x1b byte = decoded[i] ^ mask[i % 4] str_byte.append(byte) print(str_byte.decode("utf8"))
加密方法:
import struct msg_bytes = "the emperor has not been half-baked in the early days of the collapse of the road, today down three points, yizhou weakness, this serious crisis autumn".encode("utf8") token = b"\x81" # + 数据长度/运算位 + mask/数据长度 + mask/数据 + 数据 length = len(msg_bytes) if length < 126: token += struct.pack("B", length) elif length == 126: token += struct.pack("!BH", 126, length) else: token += struct.pack("!BQ", 127, length) msg = token + msg_bytes print(msg)