websocket 报文格式

WebSocket is a communication protocol providing full-duplex communication channels over a single TCP connection. It is designed to be used in web applications to enable interactive communication between a client (typically a web browser) and a server. WebSockets are initiated by a handshake using the HTTP protocol, which is then upgraded to the WebSocket protocol.

Key Features of WebSocket:

  1. Full-Duplex Communication: Both the client and server can send messages to each other independently.
  2. Single TCP Connection: After the initial handshake, communication continues over the same TCP connection.
  3. Efficient: Unlike HTTP, which requires a new connection for each request, WebSocket maintains a single connection, reducing overhead.

WebSocket Handshake

The WebSocket handshake is the process that initiates a WebSocket connection. It starts with the client sending an HTTP request to the server with an Upgrade header indicating the desire to upgrade to a WebSocket connection. The server then responds with headers confirming the upgrade.

Example of a WebSocket Handshake:

Client Request:

复制代码
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

Server Response:

复制代码
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WebSocket Frame Format

After the handshake, the client and server exchange data frames. WebSocket frames have a specific format that includes an opcode, payload length, and the actual data. Below is the structure of a WebSocket frame:

  1. FIN: 1 bit - Indicates if this is the final fragment in a message.
  2. RSV1, RSV2, RSV3: 1 bit each - Reserved for future use.
  3. Opcode: 4 bits - Defines the interpretation of the payload data.
  4. Mask: 1 bit - Indicates if the payload data is masked.
  5. Payload length: 7 bits, 7+16 bits, or 7+64 bits - The length of the payload data.
  6. Masking key: 0 or 4 bytes - Used to unmask the payload data (present if Mask is 1).
  7. Payload data: (x+y) bytes - The actual data being sent.

Example of a WebSocket Frame (Hexdump)

Below is an example of a WebSocket text frame containing the message "Hello".

Unmasked Frame:
复制代码
81 05 48 65 6C 6C 6F

Breakdown:

  • 81: FIN=1, Opcode=1 (text frame)
  • 05: Payload length is 5 bytes
  • 48 65 6C 6C 6F: Payload data "Hello"
Masked Frame:
复制代码
81 85 37 FA 21 3D 7F 9F 4D 51 58

Breakdown:

  • 81: FIN=1, Opcode=1 (text frame)
  • 85: Mask=1, Payload length is 5 bytes
  • 37 FA 21 3D: Masking key
  • 7F 9F 4D 51 58: Masked payload data

To unmask the payload data, each byte of the payload is XOR'd with the corresponding byte of the masking key. Here's how to unmask the payload data in the example above:

  1. 7F ^ 37 = 48 (H)
  2. 9F ^ FA = 65 (e)
  3. 4D ^ 21 = 6C (l)
  4. 51 ^ 3D = 6C (l)
  5. 58 ^ 7F = 6F (o)

The unmasked payload data is "Hello".

Conclusion

WebSocket is a protocol based on TCP that enables full-duplex communication between a client and server over a single connection. It starts with an HTTP handshake and then switches to the WebSocket protocol for continuous communication. The protocol uses a specific frame format to exchange messages.

Below is a simple demo of WebSocket communication in C. This example will include a basic WebSocket server using the libwebsockets library, which is a lightweight C library for WebSocket clients and servers.

Prerequisites

  1. Install the libwebsockets library. On Ubuntu, you can install it using:

    bash 复制代码
    sudo apt-get install libwebsockets-dev

WebSocket Server Example

c 复制代码
#include <libwebsockets.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>

static int interrupted;

static const struct lws_protocols protocols[] = {
    {
        "example-protocol",
        [](struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
            switch (reason) {
                case LWS_CALLBACK_ESTABLISHED:
                    lwsl_user("Connection established\n");
                    break;
                case LWS_CALLBACK_RECEIVE:
                    lwsl_user("Received data: %s\n", (char *)in);
                    lws_write(wsi, (unsigned char *)in, len, LWS_WRITE_TEXT);
                    break;
                default:
                    break;
            }
            return 0;
        },
        0, 0, 0, 0
    },
    { NULL, NULL, 0, 0, 0, 0 }
};

static void sigint_handler(int sig) {
    interrupted = 1;
}

int main(void) {
    struct lws_context_creation_info info;
    struct lws_context *context;

    signal(SIGINT, sigint_handler);

    memset(&info, 0, sizeof info);
    info.port = 7681;
    info.protocols = protocols;
    info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;

    context = lws_create_context(&info);
    if (!context) {
        lwsl_err("lws_create_context failed\n");
        return 1;
    }

    while (!interrupted) {
        lws_service(context, 1000);
    }

    lws_context_destroy(context);

    return 0;
}

Explanation

  • Libraries and Headers : The example uses the libwebsockets library.
  • Signal Handling : A signal handler to cleanly exit the server on Ctrl+C.
  • Protocols: Define the WebSocket protocols, in this case, "example-protocol".
  • Callback Function: This function handles WebSocket events. It prints messages when a connection is established and when data is received. It also echoes the received data back to the client.
  • Context Creation: Setup and creation of the WebSocket context.
  • Service Loop: The main loop where the server waits for and processes WebSocket events.
  • Cleanup: Clean up and free resources on exit.

Compilation

To compile the code, save it to a file (e.g., websocket_server.c) and use the following command:

bash 复制代码
gcc websocket_server.c -o websocket_server -lwebsockets

Running the Server

Execute the compiled program:

bash 复制代码
./websocket_server

Testing the WebSocket Server

You can use a WebSocket client (e.g., a browser or a WebSocket client tool like wscat) to connect to the server:

bash 复制代码
npm install -g wscat
wscat -c ws://localhost:7681

After connecting, you can send messages, and the server will echo them back.

This example demonstrates a simple WebSocket server that can be expanded upon to handle more complex interactions and protocols.

握手请求

GET /ws/v2?aid=35&device_id=2256622095183710&access_key=4c344a03d3473afa881d8377f45dbeb6&fpid=1&sdk_version=3&iid=1896027950179704&pl=0&ne=1&version_code=91710&sid=11f8f93ec399434ca20a1b992abad1b7 HTTP/1.1

Host: frontier100-toutiao.toutiaoapi.com

Connection: Upgrade

Pragma: no-cache

Cache-Control: no-cache

x-support-ack: 1

Upgrade: websocket

Origin: wss://frontier-toutiao.snssdk.com

Sec-WebSocket-Version: 13

x-tt-store-region: cn-bj

x-tt-store-region-src: did

x-tt-request-tag: s=-1;p=1

X-SS-DP: 35

x-tt-trace-id: 00-2ac33dc5010c3808c8136bd3d7d70023-2ac33dc5010c3808-01

User-Agent: Dalvik/2.1.0 (Linux; U; Android 13; SM-E5260 Build/TP1A.220624.014) NewsArticle/9.1.7 cronet/TTNetVersion:437fcb60 2022-11-09 QuicVersion:22f74f01 2022-10-11

Accept-Encoding: gzip, deflate, br

X-Cylons: jQ1ABID3KlKFZuGKLcqhMHVY

Sec-WebSocket-Key: lSdFzLlNEFY+wI+VBlbOTA==

Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

Sec-WebSocket-Protocol: pbbp2

握手响应

HTTP/1.1 101 Switching Protocols

Server: nginx

Date: Tue, 07 Feb 2023 07:24:43 GMT

Content-Type: application/octet-stream

Connection: upgrade

Upgrade: websocket

Sec-WebSocket-Accept: 7cCulc1ObP4idNxTd4sftSwszOU=

Sec-Websocket-Protocol: pbbp2

Handshake-Status: 0

Handshake-Msg: OK

Handshake-Options: ping-interval=30;

tt-idc-switch: 10000@20230130174459

Access-Control-Expose-Headers: tt-idc-switch

server-timing: inner; dur=3

x-tt-trace-host: 01bfda85b24fa255716a400b95f35865e801de7aa0619c3c851990fc82fb61148404fccbeeeebebdba77ee9c062919ed5fd23f4b558e9975cd3763c12d0676afcee3b1d537faa85513bf792c004d971b2b7e12cb70b9902274abf845399cff1539

x-tt-trace-tag: id=00;cdn-cache=miss

x-tt-trace-id: 00-2ac33dc5010c3808c8136bd3d7d70023-2ac33dc5010c3808-01

相关推荐
云边云科技_云网融合1 小时前
零售餐饮门店网络搭建:POS 交易稳定保障、IoT 设备联网运维、门店带宽优化、多终端并发适配
网络·物联网·零售
luj_17682 小时前
一线一区一变破解人盯人防守密码
开发语言·网络·c++·经验分享·算法
我的小卷呀3 小时前
Linux ip 命令底层逻辑与实战指南
linux·运维·c语言·网络协议·tcp/ip·网络安全
luj_17683 小时前
中锋卡位与开放线博弈
c语言·开发语言·网络·经验分享·算法
数据知道3 小时前
AES 加密实战——模式选择(ECB/CBC/GCM)与安全陷阱
前端·网络·安全
扬扬的三格电力笔记3 小时前
编码器信号远距离传输总出错?聊聊 HTL/TTL 转光纤模块,解决编码器干扰与距离难题
网络·嵌入式硬件
FW-Linker4 小时前
什么是5G直播背包?广电记者外场推流入门指南
服务器·网络·5g
sxgzzn4 小时前
新能源电站升压站状态监控方案设计——并网合规要点
网络
Soonyang Zhang4 小时前
使用wintun构建tcp中转服务
网络·网络协议·tcp/ip
星恒讯工业路由器4 小时前
市政监控进入5G RedCap时代:轻量化5G如何解决户外监控联网难题
网络·物联网·5g·智能路由器·工业路由器·5g redcap·市政监控