websocket工作原理


websocket工作原理

websocket是什么?

websocket是一套類似於http的協議。

擴展:

  http協議:\r\n分割、請求頭和請求體\r\n分割、無狀態、短連接。

{'GATEWAY_INTERFACE': 'CGI/1.1',
 'SERVER_SOFTWARE': 'gevent/1.4 Python/3.6',
 'SCRIPT_NAME': '', 
'wsgi.version': (1, 0), 
'wsgi.multithread': False, 
'wsgi.multiprocess': False, 
'wsgi.run_once': False, 
'wsgi.url_scheme': 'http',
 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding=
'UTF-8'>, 
'SERVER_NAME': 'PC-20180312LANS',
 'SERVER_PORT': '9527',
 'REQUEST_METHOD': 'GET', 
'PATH_INFO': '/conn_ws', 
'QUERY_STRING': '', 
'SERVER_PROTOCOL': 'HTTP/1.1', 
'REMOTE_ADDR': '192.168.xx.xxx',
 'REMOTE_PORT': '53449',
 'HTTP_HOST': '192.168.xx.xxx:9527',
 'HTTP_CONNECTION': 'keep-alive', 
'HTTP_UPGRADE_INSECURE_REQUESTS': '1',
 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121Safari/537.36',
 'HTTP_ACCEPT': 'text/html,
application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
 'HTTP_ACCEPT_ENCODING': 'gzip, deflate', 
'HTTP_ACCEPT_LANGUAGE': 'zh,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7', 'wsgi.input': <gevent.pywsgi.Input object at 0x0000000003B36C48>, 'wsgi.input_terminated': True,
 'werkzeug.request': <Request 'http://192.168.11.133:9527/conn_ws' [GET]>}
http協議:

  websocket協議:\r\n分割,創建連接后不斷開、驗證+數據加密;

{'GATEWAY_INTERFACE': 'CGI/1.1', 
'SERVER_SOFTWARE': 'gevent/1.4 Python/3.6',
 'SCRIPT_NAME': '', 
'wsgi.version': (1, 0), 
'wsgi.multithread': False, 
'wsgi.multiprocess': False, 
'wsgi.run_once': False, 
'wsgi.url_scheme': 'http',
 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding=
'UTF-8'>, 
'SERVER_NAME': 'PC-20180312LANS',
 'SERVER_PORT': '9527', 'REQUEST_METHOD': 'GET', 
'PATH_INFO': '/conn_ws', 'QUERY_STRING': '', 
'SERVER_PROTOCOL': 'HTTP/1.1', 
'REMOTE_ADDR': '127.0.0.1', 
'REMOTE_PORT': '53571',
 'HTTP_HOST': '127.0.0.1:9527', 
'HTTP_CONNECTION': 'Upgrade', 
'HTTP_PRAGMA': 'no-cache', 
'HTTP_CACHE_CONTROL': 'no-cache',
 'HTTP_UPGRADE': 'websocket', 
'HTTP_ORIGIN': 'http://localhost:63342', 
'HTTP_SEC_WEBSOCKET_VERSION': '13',
 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36', 
'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 
'HTTP_ACCEPT_LANGUAGE': 'zh,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7', 'HTTP_SEC_WEBSOCKET_KEY': 'ET/SDQc1sI+uhxm+EjHLcw==', 'HTTP_SEC_WEBSOCKET_EXTENSIONS': 'permessage-deflate; client_max_window_bits', 
'wsgi.input': <gevent.pywsgi.Input object at 0x0000000003BC9468>, 'wsgi.input_terminated': True, 
'wsgi.websocket_version': '13',
Websocket協議:

  其中主要不同的參數為:

'wsgi.websocket': <geventwebsocket.websocket.WebSocket object at 0x0000000003BC8528>,
'werkzeug.request': <Request 'http://127.0.0.1:9527/conn_ws' [GET]>}

websocket本質:

  就是一個創建連接后不斷開的socket,當連接成功之后:

  客戶端(瀏覽器)會自動向服務端發送消息,包含: Sec-WebSocket-Key : jocLOLLq1BQWp0aZgEWL5A==

  通過header_dict["Sec-WebSocket-Key"] = i.split(":")[1].strip()返回一個header_dict字典

  服務端接收之后,會對於該數據進行加密:

value = headers['Sec-WebSocket-Key'] + magic_string
ac = base64.b64encode(hashlib.sha1(value.encode('utf-8')).digest())
其中:
magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11

 

構造響應頭:

1 response_tpl = "HTTP/1.1 101 Switching Protocols\r\n" \
2                "Upgrade:websocket\r\n" \
3                "Connection: Upgrade\r\n" \
4                "Sec-WebSocket-Accept: %s\r\n" \
5                "WebSocket-Location: ws://127.0.0.1:9527\r\n\r\n"

 

發送客戶端(瀏覽器)

  -建立:雙工通道,接下來就可以進行收發數據  

  -發送的數據是經過加密數據,

  -解密根據payload_len的值進行處理:

  -payload_len <= 125

  -payload_len == 126

  -payload_len == 127

  獲取內容:

  -mask_key

  數據

  根據mask_key和數據進行位運算,就可以把值解析出來。

 1 hashstr = b'\x81\x83\xceH\xb6\x85\xffz\x85'
 2 # b'\x81    \x83    \xceH\xb6\x85\xffz\x85'
 3 # 將第二個字節也就是 \x83 第9-16位 進行與127進行位運算
 4 # 127二進制為01111111 進行"與"位運算 結果是兩個數的最小值
 5 payload = hashstr[1] & 127
 6 print(payload)
 7 if payload == 127:
 8      extend_payload_len = hashstr[2:10]
 9      mask = hashstr[10:14]
10      decoded = hashstr[14:]
11 # 當位運算結果等於127時,則第3-10個字節為數據長度
12 # 第11-14字節為mask 解密所需字符串
13 # 則數據為第15字節至結尾
14 
15 if payload == 126:
16      extend_payload_len = hashstr[2:4]
17      mask = hashstr[4:8]
18      decoded = hashstr[8:]
19 # 當位運算結果等於126時,則第3-4個字節為數據長度
20 # 第5-8字節為mask 解密所需字符串
21 # 則數據為第9字節至結尾
22  
23 if payload <= 125:
24      extend_payload_len = None
25      mask = hashstr[2:6]
26      decoded = hashstr[6:]
27  
28 # 當位運算結果小於等於125時,則這個數字就是數據的長度
29 # 第3-6字節為mask 解密所需字符串
30 # 則數據為第7字節至結尾
31  
32 str_byte = bytearray()
33  
34 for i in range(len(decoded)):
35      byte = decoded[i] ^ mask[i % 4]
36      str_byte.append(byte)
37  
38 print(str_byte.decode("utf8"))
解密:
 1 import struct
 2 msg_bytes = "hello".encode("utf8")
 3 token = b"\x81"
 4 length = len(msg_bytes)
 5 
 6 if length < 126:
 7     token += struct.pack("B", length)
 8 elif length == 126:
 9     token += struct.pack("!BH", 126, length)
10 else:
11     token += struct.pack("!BQ", 127, length)
12  
13 msg = token + msg_bytes
14  
15 print(msg)
加密:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM