您的位置:

WebSocket Header解析

一、WebSocket Header概述

WebSocket是HTML5中一种新的协议,它实现了浏览器与服务器的全双工通信,使得客户端和服务器可以进行实时的数据传输。搭建WebSocket服务器,需要先了解WebSocket连接建立的过程中的头部信息。

二、WebSocket Header格式

在建立WebSocket连接时,浏览器和服务器之间会进行协议升级,即使用HTTP协议发起一个握手请求来升级连接。发起握手请求时,浏览器会在请求头中加上"Sec-WebSocket-Key"和"Sec-WebSocket-Version"这两个字段,服务器需要根据这两个字段来判断是否支持WebSocket协议,如支持则必须回应101状态码,并在响应头中加入"Upgrade"和"Connection"这两个字段。

GET /[path] HTTP/1.1
Host: [host]
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: [key]
Sec-WebSocket-Version: [version]

"Sec-WebSocket-Key"是一个随机字符串,服务器需要使用这个字符串来加密后再转换成字节数组,然后通过SHA-1计算出20个字节的哈希值,最后将此哈希值的base64编码作为响应头中的"Sec-WebSocket-Accept"字段。

三、WebSocket Header字段解析

1. Upgrade

"Upgrade"是请求头中的一个字段,表示浏览器希望升级到哪种协议。在升级WebSocket时,其值为"websocket"。

2. Connection

"Connection"是请求头中的一个字段,表示浏览器希望建立的连接类型。在升级WebSocket时,其值为"Upgrade"。

3. Sec-WebSocket-Key

"Sec-WebSocket-Key"是浏览器生成的随机字符串,用于计算响应值。服务器需要将这个字符串与一个魔术字符串 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 拼接,然后计算 SHA1 哈希值。最后,服务器以 Base64 编码方式返回哈希值,并在响应头中添加"Sec-WebSocket-Accept"字段,告诉浏览器解码响应头并验证key是否正确。

4. Sec-WebSocket-Version

"Sec-WebSocket-Version"是请求头中的一个字段,表示浏览器支持的WebSocket协议版本号。

5. Sec-WebSocket-Accept

"Sec-WebSocket-Accept"是响应头中的一个字段,表示服务器计算出来的响应值,也就是经过base64编码后的字符串。这个值需要被浏览器验证,以确保握手请求是受信任的。

四、WebSocket Header参考代码

1. Python实现WebSocket握手过程

def handshake(sock):
    """
    handshake for WebSocket
    """
    data = sock.recv(1024)
    headers = {}
    lines = data.decode('utf-8').splitlines()

    for l in lines:
        parts = l.split(": ", 1)
        if len(parts) == 2:
            headers[parts[0]] = parts[1]

    headers['Sec-WebSocket-Accept'] = b64encode(
        sha1((headers['Sec-WebSocket-Key'] + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").encode('utf-8')).digest())

    response = \
        b"HTTP/1.1 101 Web Socket Protocol Handshake\r\n" \
        b"Upgrade: websocket\r\n" \
        b"Connection: Upgrade\r\n" \
        b"Sec-WebSocket-Accept: " + headers['Sec-WebSocket-Accept'] + b"\r\n\r\n"

    sock.send(response)

2. JavaScript实现WebSocket握手过程

var socket = new WebSocket("ws://localhost:8080/");
socket.onopen = function() {
    var key = generateWebSocketKey();
    var headers = {
        "Upgrade": "websocket",
        "Connection": "Upgrade",
        "Sec-WebSocket-Key": key,
        "Sec-WebSocket-Version": "13"
    };

    socket.send(buildWebSocketHandshake(headers));
}

function generateWebSocketKey() {
    var buffer = new Uint32Array(1);
    var bytes = new Uint8Array(buffer.buffer);

    window.crypto.getRandomValues(buffer);

    var key = '';

    for (var byte of bytes) {
        key += String.fromCharCode(byte);
    }

    return btoa(key);
}

function buildWebSocketHandshake(headers) {
    var lines = [];

    for (var k in headers) {
        lines.push(k + ": " + headers[k]);
    }

    var handshake = "GET / HTTP/1.1\r\n" +
        lines.join("\r\n") + "\r\n\r\n";

    return handshake;
}

五、总结

WebSocket的Header信息是WebSocket建立连接的重要组成部分,其握手过程确保通信双方都能正常解析对方发来的信息。通过查看header信息,可以轻松了解WebSocket请求的详细内容,对于开发和调试WebSocket应用程序非常有帮助。