websocket协议

什么是websocket协议

websocket协议类似于http协议

http   :数据按 分割,请求头和请求体按  分割  是短连接、无状态基于tcp协议

websocket:数据按 分割,创建连接后不断开,创建连接是需要先验证,发送数据时要加密

websocket本质

1、创建一个建立连接之后不断开的socket

2、创建连接(握手)

  -客户端向服务端发送请求

  -服务端获取请求头中的Sec-WebSocket-key的值,将此值+magic_string(魔法字符串)进行hashlib和base64加密

  -构造响应头,里面包含Sec-WebSocket-Accept: 加密后的值

  -返送给客户端

  -客户端再拿到加密的数据,解密进行验证

3、连接建立成功后:建立双工通道(同一时间,即可发送数据也可接受数据),进行数据通信

  -发送的数据都是加密的,解密后,根据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('

', 1)
    header_list = header.split('
')
    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
" 
      "Upgrade:websocket
" 
      "Connection: Upgrade
" 
      "Sec-WebSocket-Accept: %s
" 
      "WebSocket-Location: ws://127.0.0.1:8002

"

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

待续.....

原文地址:https://www.cnblogs.com/caochao-/p/9053069.html