websocket協議

什麼是websocket協議

websocket協議相似於http協議html

http   :數據按 \r\n 分割,請求頭和請求體按 \r\n\r\n 分割  是短鏈接、無狀態基於tcp協議jquery

websocket:數據按 \r\n分割,建立鏈接後不斷開,建立鏈接是須要先驗證,發送數據時要加密web

websocket本質

一、建立一個創建鏈接以後不斷開的socket服務器

二、建立鏈接(握手)websocket

  -客戶端向服務端發送請求app

  -服務端獲取請求頭中的Sec-WebSocket-key的值,將此值+magic_string(魔法字符串)進行hashlib和base64加密socket

  -構造響應頭,裏面包含Sec-WebSocket-Accept: 加密後的值tcp

  -返送給客戶端ide

  -客戶端再拿到加密的數據,解密進行驗證ui

三、鏈接創建成功後:創建雙工通道(同一時間,便可發送數據也可接受數據),進行數據通訊

  -發送的數據都是加密的,解密後,根據payload_len的值獲取內容(payload_len的值至關於報頭)

    -payload_len <=125

    -payload_len ==126

    -payload_len ==127

  -將獲取的內容分爲

    -mask_key

    -數據

    根據mask_key和數據進行位運算,最後解析出數據

  

示例:

參考:http://www.cnblogs.com/wupeiqi/p/6558766.html
import socket
import base64
import hashlib

def get_headers(data):
    """
    將請求頭格式化成字典
    :param data:
    :return:
    """
    header_dict = {}
    data = str(data, encoding='utf-8')
    header, body = data.split('\r\n\r\n', 1)
    header_list = header.split('\r\n')
    for i in range(0, len(header_list)):
        if i == 0:
            if len(header_list[i].split(' ')) == 3:
                header_dict['method'], header_dict['url'], header_dict['protocol'] = header_list[i].split(' ')
        else:
            k, v = header_list[i].split(':', 1)
            header_dict[k] = v.strip()
    return header_dict

def send_msg(conn, msg_bytes):
    """
    WebSocket服務端向客戶端發送消息
    :param conn: 客戶端鏈接到服務器端的socket對象,即: conn,address = socket.accept()
    :param msg_bytes: 向客戶端發送的字節
    :return:
    """
    import struct

    token = b"\x81"
    length = len(msg_bytes)
    if length < 126:
        token += struct.pack("B", length)
    elif length <= 0xFFFF:
        token += struct.pack("!BH", 126, length)
    else:
        token += struct.pack("!BQ", 127, length)

    msg = token + msg_bytes
    conn.send(msg)
    return True

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('127.0.0.1', 8002))
sock.listen(5)
# 等待用戶鏈接
conn, address = sock.accept()

data = conn.recv(8096)

header_dict = get_headers(data)
# 在驗證環節對Sec-WebSocket-Key對應的值進行加密

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


# 構造響應頭
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:8002\r\n\r\n"

response = response_tpl %(str(ac,encoding='utf-8'),)

conn.sendall(bytes(response,encoding='utf-8'))


while True:
    # 用戶發過來的加密的數據
    info = conn.recv(8096)
    payload_len = info[1] & 127
    if payload_len == 127:
        extend_payload_len = info[2:10]
        mask = info[10:14]
        decoded = info[14:]
    elif payload_len == 126:
        extend_payload_len = info[2:4]
        mask = info[4:8]
        decoded = info[8:]
    else:
        extend_payload_len = None
        mask = info[2:6]
        decoded = info[6:]

    bytes_list = bytearray()
    for i in range(len(decoded)):
        chunk = decoded[i] ^ mask[i % 4]
        bytes_list.append(chunk)
    body = str(bytes_list, encoding='utf-8')
    print(body)

    body = body + 'sb'

    send_msg(conn,bytes(body,encoding='utf-8'))
app.py
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
    <style>
        .msg-item{
            padding: 5px;
            border: 1px;
            margin: 0 5px;
        }
    </style>
</head>
<body>
    <h1>首頁</h1>
    <div>
        <h2>發送消息</h2>
        <input id="msg" type="text"  /> <input type="button" value="發送" onclick="sendMsg()">
        <h2>接收消息</h2>
        <div id="container">

        </div>
    </div>

    <script src="/static/jquery-3.3.1.min.js"></script>
    <script>

        ws = new WebSocket('ws://192.168.12.42:5000/test');
        ws.onmessage = function (event) {
            var tag = document.createElement('div');
            tag.className = 'msg-item';
            tag.innerText = event.data;
            $('#container').append(tag);
        }

        function sendMsg() {
            ws.send($('#msg').val());
        }
    </script>
</body>
</html>
index.html

待續.....

相關文章
相關標籤/搜索