【Mongoose笔记】Websocket 服务器
简介
Mongoose 笔记系列用于记录学习 Mongoose 的一些内容。
Mongoose 是一个 C/C++ 的网络库。它为 TCP、UDP、HTTP、WebSocket、MQTT 实现了事件驱动的、非阻塞的 API。
项目地址:
https://github.com/cesanta/mongoose
学习
下面通过学习 Mongoose 项目代码中的 websocket-server 示例程序 ,来学习如何使用 Mongoose 实现一个简单的 Websocket 服务器。使用树莓派平台进行开发验证。
websocket-server 的示例程序很短,代码如下:
// Copyright (c) 2020 Cesanta Software Limited
// All rights reserved
//
// Example Websocket server. See https://mongoose.ws/tutorials/websocket-server/
#include "mongoose.h"
static const char *s_listen_on = "ws://localhost:8000";
static const char *s_web_root = ".";
// This RESTful server implements the following endpoints:
// /websocket - upgrade to Websocket, and implement websocket echo server
// /rest - respond with JSON string {"result": 123}
// any other URI serves static files from s_web_root
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_OPEN) {
// c->is_hexdumping = 1;
} else if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_http_match_uri(hm, "/websocket")) {
// Upgrade to websocket. From now on, a connection is a full-duplex
// Websocket connection, which will receive MG_EV_WS_MSG events.
mg_ws_upgrade(c, hm, NULL);
} else if (mg_http_match_uri(hm, "/rest")) {
// Serve REST response
mg_http_reply(c, 200, "", "{\"result\": %d}\n", 123);
} else {
// Serve static files
struct mg_http_serve_opts opts = {.root_dir = s_web_root};
mg_http_serve_dir(c, ev_data, &opts);
}
} else if (ev == MG_EV_WS_MSG) {
// Got websocket frame. Received data is wm->data. Echo it back!
struct mg_ws_message *wm = (struct mg_ws_message *) ev_data;
mg_ws_send(c, wm->data.ptr, wm->data.len, WEBSOCKET_OP_TEXT);
}
(void) fn_data;
}
int main(void) {
struct mg_mgr mgr; // Event manager
mg_mgr_init(&mgr); // Initialise event manager
printf("Starting WS listener on %s/websocket\n", s_listen_on);
mg_http_listen(&mgr, s_listen_on, fn, NULL); // Create HTTP listener
for (;;) mg_mgr_poll(&mgr, 1000); // Infinite event loop
mg_mgr_free(&mgr);
return 0;
}
下面我们从main
函数开始分析代码。
首先是变量定义,其中struct mg_mgr
是用于保存所有活动连接的事件管理器。
struct mg_mgr mgr; // Event manager
初始化一个事件管理器,将上面的 struct mg_mgr
变量 mgr
中的数据进行初始化。
mg_mgr_init(&mgr); // Initialise event manager
打印日志,将监听地址s_listen_on
打印出来。
printf("Starting WS listener on %s/websocket\n", s_listen_on);
s_listen_on
是一个静态全局变量,默认值为ws://localhost:8000
,监听本地主机,端口号 8000。
static const char *s_listen_on = "ws://localhost:8000";
通过 mg_http_listen
创建一个 HTTP 监听连接,监听地址s_listen_on
,其中fn
是事件处理函数。
mg_http_listen(&mgr, s_listen_on, fn, NULL); // Create HTTP listener
接下来是事件循环,mg_mgr_poll
遍历所有连接,接受新连接,发送和接收数据,关闭连接,并为各个事件调用事件处理函数。
for (;;) mg_mgr_poll(&mgr, 1000); // Infinite event loop
mg_mgr_free
用于关闭所有连接,释放所有资源。
mg_mgr_free(&mgr);
分析完main
函数后,我们看下事件处理函数fn
的代码。
首先是判断是否接收到 MG_EV_OPEN
事件,收到MG_EV_OPEN
事件表示已创建连接。该事件在分配连接并将其添加到事件管理器之后立即发送。
if (ev == MG_EV_OPEN) {
// c->is_hexdumping = 1;
}
接下来判断是否接收到的MG_EV_HTTP_MSG
事件,如果是则开始 HTTP 请求的处理。
} else if (ev == MG_EV_HTTP_MSG) {
将函数参数ev_data
转换为 struct mg_http_message
,其中包含已解析的 HTTP 请求。
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
使用mg_http_match_uri
函数检查 HTTP 请求中 URI 是否等于/websocket
,如果是的话则调用mg_ws_upgrade
函数将 HTTP 连接转换为 Websocket 连接,连接变为全双工,后续收到消息时将触发的是 MG_EV_WS_MSG
事件。
if (mg_http_match_uri(hm, "/websocket")) {
// Upgrade to websocket. From now on, a connection is a full-duplex
// Websocket connection, which will receive MG_EV_WS_MSG events.
mg_ws_upgrade(c, hm, NULL);
}
继续使用mg_http_match_uri
函数,检查 HTTP 请求中 URI 是否等于/rest
,如果是的话回复响应 JSON 字符串 {"result": 123}
。其中mg_http_reply
函数用于发送简单的 HTTP 响应,200
表示返回的 HTTP 状态码,""
表示额外的头信息,这里没有所以为空,"{\"result\": %d}\n", 123
部分就是返回的 HTTP 报文主体。
} else if (mg_http_match_uri(hm, "/rest")) {
// Serve REST response
mg_http_reply(c, 200, "", "{\"result\": %d}\n", 123);
}
如果收到的是其他任何的 URI ,都是从s_web_root
目录提供静态文件服务,s_web_root
的默认值为当前目录。
} else {
// Serve static files
struct mg_http_serve_opts opts = {.root_dir = s_web_root};
mg_http_serve_dir(c, ev_data, &opts);
}
接下来判断是否接收到的MG_EV_WS_MSG
事件,表示接收到 Websocket 消息。
} else if (ev == MG_EV_WS_MSG) {
将函数参数ev_data
转换为 struct mg_ws_message
,这个结构体表示 WebSocket 消息。
struct mg_ws_message *wm = (struct mg_ws_message *) ev_data;
将收到的消息wm->data.ptr
,直接通过mg_ws_send
函数原封不动的回复回去。
mg_ws_send
函数用于 WebSocket 消息的发送,WEBSOCKET_OP_TEXT
是 WebSocket 消息类型之一,表示要发送的有效载荷数据为文本数据。
mg_ws_send(c, wm->data.ptr, wm->data.len, WEBSOCKET_OP_TEXT);
到这里 websocket-server 的示例程序代码就都解析完了,下面实际运行一下 websocket-server 程序。
打开示例程序,编译并运行:
pi@raspberrypi:~ $ cd Desktop/study/mongoose/examples/websocket-server/
pi@raspberrypi:~/Desktop/study/mongoose/examples/websocket-server $ make
cc ../../mongoose.c -I../.. -W -Wall -DMG_ENABLE_LINES=1 -o example main.c
./example
Starting WS listener on ws://localhost:8000/websocket
这个时候我们的服务器已经运行起来了。
接下来要测试下这个 WebSocket 服务器,我们可以使用 websocket-server 示例程序目录下的 test.html
,这是一个 WebSocket 测试客户端。
在浏览器中,输入 URL http://localhost:8000/test.html:
然后点击 connect
按钮连接 WebSocket 服务器:
然后在文本输入框中输入你想发送的信息,例如输入一句Hello World!
,然后点击send message
按钮发送消息:
可以看到客户端收到了 WebSocket 服务器回复的Hello World!
消息。
我们发现 WebSocket 服务器这边没有打印任何日志,如果需要查看更多的信息,例如收发的消息,可以将事件处理函数fn
里的被屏蔽的代码c->is_hexdumping = 1;
打开,开启Hexdump in/out traffic功能,会将接收和发送的数据以16进制的形式打印出来。
if (ev == MG_EV_OPEN) {
c->is_hexdumping = 1;
}
然后重新编译运行,再将上面的连接发送等操作重新操作一遍。
pi@raspberrypi:~/Desktop/study/mongoose/examples/websocket-server $ make clean all
rm -rf example *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb
cc ../../mongoose.c -I../.. -W -Wall -DMG_ENABLE_LINES=1 -o example main.c
./example
Starting WS listener on ws://localhost:8000/websocket
1bf531 2 sock.c:112:iolog
-- 2 127.0.0.1:8000 <- 127.0.0.1:59652 519
0000 47 45 54 20 2f 74 65 73 74 2e 68 74 6d 6c 20 48 GET /test.html H
0010 54 54 50 2f 31 2e 31 0d 0a 48 6f 73 74 3a 20 6c TTP/1.1..Host: l
0020 6f 63 61 6c 68 6f 73 74 3a 38 30 30 30 0d 0a 43 ocalhost:8000..C
0030 6f 6e 6e 65 63 74 69 6f 6e 3a 20 6b 65 65 70 2d onnection: keep-
0040 61 6c 69 76 65 0d 0a 55 70 67 72 61 64 65 2d 49 alive..Upgrade-I
0050 6e 73 65 63 75 72 65 2d 52 65 71 75 65 73 74 73 nsecure-Requests
0060 3a 20 31 0d 0a 55 73 65 72 2d 41 67 65 6e 74 3a : 1..User-Agent:
0070 20 4d 6f 7a 69 6c 6c 61 2f 35 2e 30 20 28 58 31 Mozilla/5.0 (X1
0080 31 3b 20 4c 69 6e 75 78 20 61 72 6d 76 37 6c 29 1; Linux armv7l)
0090 20 41 70 70 6c 65 57 65 62 4b 69 74 2f 35 33 37 AppleWebKit/537
00a0 2e 33 36 20 28 4b 48 54 4d 4c 2c 20 6c 69 6b 65 .36 (KHTML, like
00b0 20 47 65 63 6b 6f 29 20 52 61 73 70 62 69 61 6e Gecko) Raspbian
00c0 20 43 68 72 6f 6d 69 75 6d 2f 37 38 2e 30 2e 33 Chromium/78.0.3
00d0 39 30 34 2e 31 30 38 20 43 68 72 6f 6d 65 2f 37 904.108 Chrome/7
00e0 38 2e 30 2e 33 39 30 34 2e 31 30 38 20 53 61 66 8.0.3904.108 Saf
00f0 61 72 69 2f 35 33 37 2e 33 36 0d 0a 53 65 63 2d ari/537.36..Sec-
0100 46 65 74 63 68 2d 55 73 65 72 3a 20 3f 31 0d 0a Fetch-User: ?1..
0110 41 63 63 65 70 74 3a 20 74 65 78 74 2f 68 74 6d Accept: text/htm
0120 6c 2c 61 70 70 6c 69 63 61 74 69 6f 6e 2f 78 68 l,application/xh
0130 74 6d 6c 2b 78 6d 6c 2c 61 70 70 6c 69 63 61 74 tml+xml,applicat
0140 69 6f 6e 2f 78 6d 6c 3b 71 3d 30 2e 39 2c 69 6d ion/xml;q=0.9,im
0150 61 67 65 2f 77 65 62 70 2c 69 6d 61 67 65 2f 61 age/webp,image/a
0160 70 6e 67 2c 2a 2f 2a 3b 71 3d 30 2e 38 2c 61 70 png,*/*;q=0.8,ap
0170 70 6c 69 63 61 74 69 6f 6e 2f 73 69 67 6e 65 64 plication/signed
0180 2d 65 78 63 68 61 6e 67 65 3b 76 3d 62 33 0d 0a -exchange;v=b3..
0190 53 65 63 2d 46 65 74 63 68 2d 53 69 74 65 3a 20 Sec-Fetch-Site:
01a0 6e 6f 6e 65 0d 0a 53 65 63 2d 46 65 74 63 68 2d none..Sec-Fetch-
01b0 4d 6f 64 65 3a 20 6e 61 76 69 67 61 74 65 0d 0a Mode: navigate..
01c0 41 63 63 65 70 74 2d 45 6e 63 6f 64 69 6e 67 3a Accept-Encoding:
01d0 20 67 7a 69 70 2c 20 64 65 66 6c 61 74 65 2c 20 gzip, deflate,
01e0 62 72 0d 0a 41 63 63 65 70 74 2d 4c 61 6e 67 75 br..Accept-Langu
01f0 61 67 65 3a 20 7a 68 2d 43 4e 2c 7a 68 3b 71 3d age: zh-CN,zh;q=
0200 30 2e 39 0d 0a 0d 0a 0.9....
1bf533 2 sock.c:112:iolog
-- 2 127.0.0.1:8000 -> 127.0.0.1:59652 1687
0000 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d HTTP/1.1 200 OK.
0010 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 74 .Content-Type: t
0020 65 78 74 2f 68 74 6d 6c 3b 20 63 68 61 72 73 65 ext/html; charse
0030 74 3d 75 74 66 2d 38 0d 0a 45 74 61 67 3a 20 22 t=utf-8..Etag: "
0040 31 36 36 37 37 32 38 37 31 39 2e 31 35 38 31 22 1667728719.1581"
0050 0d 0a 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 ..Content-Length
0060 3a 20 31 35 38 31 0d 0a 0d 0a 3c 21 44 4f 43 54 : 1581....<!DOCT
0070 59 50 45 20 68 74 6d 6c 3e 0a 3c 68 74 6d 6c 20 YPE html>.<html
0080 6c 61 6e 67 3d 22 65 6e 22 3e 0a 20 20 3c 62 6f lang="en">. <bo
0090 64 79 3e 0a 20 20 20 20 3c 68 31 3e 57 65 62 73 dy>. <h1>Webs
00a0 6f 63 6b 65 74 20 74 65 73 74 20 63 6c 69 65 6e ocket test clien
00b0 74 3c 2f 68 31 3e 0a 20 20 20 20 3c 69 6e 70 75 t</h1>. <inpu
00c0 74 20 69 64 3d 22 75 72 6c 22 20 74 79 70 65 3d t id="url" type=
00d0 22 74 65 78 74 22 20 70 6c 61 63 65 68 6f 6c 64 "text" placehold
00e0 65 72 3d 22 54 79 70 65 20 55 52 4c 22 20 76 61 er="Type URL" va
00f0 6c 75 65 3d 22 77 73 3a 2f 2f 6c 6f 63 61 6c 68 lue="ws://localh
0100 6f 73 74 3a 38 30 30 30 2f 77 65 62 73 6f 63 6b ost:8000/websock
0110 65 74 22 20 73 74 79 6c 65 3d 22 77 69 64 74 68 et" style="width
0120 3a 32 30 65 6d 3b 22 20 2f 3e 20 0a 20 20 20 20 :20em;" /> .
0130 3c 62 75 74 74 6f 6e 20 69 64 3d 22 63 6f 6e 6e <button id="conn
0140 65 63 74 22 3e 63 6f 6e 6e 65 63 74 3c 2f 62 75 ect">connect</bu
0150 74 74 6f 6e 3e 0a 20 20 20 20 3c 64 69 76 20 73 tton>. <div s
0160 74 79 6c 65 3d 22 68 65 69 67 68 74 3a 20 30 2e tyle="height: 0.
0170 33 65 6d 3b 22 3e 26 6e 62 73 70 3b 3c 2f 64 69 3em;"> </di
0180 76 3e 0a 20 20 20 20 3c 69 6e 70 75 74 20 69 64 v>. <input id
0190 3d 22 6d 65 73 73 61 67 65 22 20 74 79 70 65 3d ="message" type=
01a0 22 74 65 78 74 22 20 70 6c 61 63 65 68 6f 6c 64 "text" placehold
01b0 65 72 3d 22 54 79 70 65 20 6d 65 73 73 61 67 65 er="Type message
01c0 22 20 73 74 79 6c 65 3d 22 77 69 64 74 68 3a 20 " style="width:
01d0 32 30 65 6d 3b 22 20 2f 3e 20 0a 20 20 20 20 3c 20em;" /> . <
01e0 62 75 74 74 6f 6e 20 69 64 3d 22 73 65 6e 64 22 button id="send"
01f0 3e 73 65 6e 64 20 6d 65 73 73 61 67 65 3c 2f 62 >send message</b
0200 75 74 74 6f 6e 3e 0a 20 20 20 20 3c 64 69 76 20 utton>. <div
0210 73 74 79 6c 65 3d 22 6d 61 72 67 69 6e 2d 74 6f style="margin-to
0220 70 3a 20 31 65 6d 3b 22 3e 45 76 65 6e 74 20 6c p: 1em;">Event l
0230 6f 67 3a 3c 2f 64 69 76 3e 0a 20 20 20 20 3c 64 og:</div>. <d
0240 69 76 20 69 64 3d 22 6c 6f 67 22 20 73 74 79 6c iv id="log" styl
0250 65 3d 22 62 61 63 6b 67 72 6f 75 6e 64 3a 20 23 e="background: #
0260 65 65 65 3b 20 68 65 69 67 68 74 3a 20 31 30 65 eee; height: 10e
0270 6d 3b 20 70 61 64 64 69 6e 67 3a 20 30 2e 35 65 m; padding: 0.5e
0280 6d 3b 22 3e 3c 64 69 76 3e 0a 20 20 3c 2f 62 6f m;"><div>. </bo
0290 64 79 3e 0a 20 20 3c 73 63 72 69 70 74 3e 0a 20 dy>. <script>.
02a0 20 20 20 76 61 72 20 77 73 2c 20 45 20 3d 20 66 var ws, E = f
02b0 75 6e 63 74 69 6f 6e 28 69 64 29 20 7b 20 72 65 unction(id) { re
02c0 74 75 72 6e 20 64 6f 63 75 6d 65 6e 74 2e 67 65 turn document.ge
02d0 74 45 6c 65 6d 65 6e 74 42 79 49 64 28 69 64 29 tElementById(id)
02e0 3b 20 7d 3b 0a 20 20 20 20 76 61 72 20 75 72 6c ; };. var url
02f0 20 3d 20 45 28 27 75 72 6c 27 29 2c 20 63 6f 6e = E('url'), con
0300 6e 65 63 74 20 3d 20 45 28 27 63 6f 6e 6e 65 63 nect = E('connec
0310 74 27 29 2c 20 6d 65 73 73 61 67 65 20 3d 20 45 t'), message = E
0320 28 27 6d 65 73 73 61 67 65 27 29 2c 20 73 65 6e ('message'), sen
0330 64 20 3d 20 45 28 27 73 65 6e 64 27 29 2c 20 6c d = E('send'), l
0340 6f 67 20 3d 20 45 28 27 6c 6f 67 27 29 3b 0a 20 og = E('log');.
0350 20 20 20 76 61 72 20 65 6e 61 62 6c 65 20 3d 20 var enable =
0360 66 75 6e 63 74 69 6f 6e 28 65 6e 29 20 7b 20 6d function(en) { m
0370 65 73 73 61 67 65 2e 64 69 73 61 62 6c 65 64 20 essage.disabled
0380 3d 20 73 65 6e 64 2e 64 69 73 61 62 6c 65 64 20 = send.disabled
0390 3d 20 21 65 6e 3b 20 75 72 6c 2e 64 69 73 61 62 = !en; url.disab
03a0 6c 65 64 20 3d 20 65 6e 3b 20 63 6f 6e 6e 65 63 led = en; connec
03b0 74 2e 69 6e 6e 65 72 48 54 4d 4c 20 3d 20 65 6e t.innerHTML = en
03c0 20 3f 20 27 64 69 73 63 6f 6e 6e 65 63 74 27 20 ? 'disconnect'
03d0 3a 20 27 63 6f 6e 6e 65 63 74 27 3b 20 7d 3b 0a : 'connect'; };.
03e0 20 20 20 20 65 6e 61 62 6c 65 28 66 61 6c 73 65 enable(false
03f0 29 0a 20 20 20 20 63 6f 6e 6e 65 63 74 2e 6f 6e ). connect.on
0400 63 6c 69 63 6b 20 3d 20 66 75 6e 63 74 69 6f 6e click = function
0410 28 29 20 7b 0a 20 20 20 20 20 20 69 66 20 28 77 () {. if (w
0420 73 29 20 7b 20 77 73 2e 63 6c 6f 73 65 28 29 3b s) { ws.close();
0430 20 72 65 74 75 72 6e 3b 20 7d 0a 20 20 20 20 20 return; }.
0440 20 77 73 20 3d 20 6e 65 77 20 57 65 62 53 6f 63 ws = new WebSoc
0450 6b 65 74 28 75 72 6c 2e 76 61 6c 75 65 29 3b 0a ket(url.value);.
0460 20 20 20 20 20 20 69 66 20 28 21 77 73 29 20 72 if (!ws) r
0470 65 74 75 72 6e 3b 0a 20 20 20 20 20 20 77 73 2e eturn;. ws.
0480 6f 6e 6f 70 65 6e 20 3d 20 66 75 6e 63 74 69 6f onopen = functio
0490 6e 28 29 20 7b 20 6c 6f 67 2e 69 6e 6e 65 72 48 n() { log.innerH
04a0 54 4d 4c 20 2b 3d 20 27 43 4f 4e 4e 45 43 54 49 TML += 'CONNECTI
04b0 4f 4e 20 4f 50 45 4e 45 44 3c 62 72 2f 3e 27 3b ON OPENED<br/>';
04c0 20 7d 0a 20 20 20 20 20 20 77 73 2e 6f 6e 6d 65 }. ws.onme
04d0 73 73 61 67 65 20 3d 20 66 75 6e 63 74 69 6f 6e ssage = function
04e0 28 65 76 29 20 7b 20 6c 6f 67 2e 69 6e 6e 65 72 (ev) { log.inner
04f0 48 54 4d 4c 20 2b 3d 20 27 52 45 43 45 49 56 45 HTML += 'RECEIVE
0500 44 3a 20 27 20 2b 20 65 76 2e 64 61 74 61 20 2b D: ' + ev.data +
0510 20 27 3c 62 72 2f 3e 27 3b 20 7d 0a 20 20 20 20 '<br/>'; }.
0520 20 20 77 73 2e 6f 6e 65 72 72 6f 72 20 3d 20 66 ws.onerror = f
0530 75 6e 63 74 69 6f 6e 28 65 76 29 20 7b 20 6c 6f unction(ev) { lo
0540 67 2e 69 6e 6e 65 72 48 54 4d 4c 20 2b 3d 20 27 g.innerHTML += '
0550 45 52 52 4f 52 3a 20 27 20 2b 20 65 76 20 2b 20 ERROR: ' + ev +
0560 27 3c 62 72 2f 3e 27 3b 20 7d 0a 20 20 20 20 20 '<br/>'; }.
0570 20 77 73 2e 6f 6e 63 6c 6f 73 65 20 3d 20 66 75 ws.onclose = fu
0580 6e 63 74 69 6f 6e 28 29 20 7b 20 6c 6f 67 2e 69 nction() { log.i
0590 6e 6e 65 72 48 54 4d 4c 20 2b 3d 20 27 43 4f 4e nnerHTML += 'CON
05a0 4e 45 43 54 49 4f 4e 20 43 4c 4f 53 45 44 3c 62 NECTION CLOSED<b
05b0 72 2f 3e 27 3b 20 65 6e 61 62 6c 65 28 66 61 6c r/>'; enable(fal
05c0 73 65 29 3b 20 77 73 20 3d 20 6e 75 6c 6c 3b 20 se); ws = null;
05d0 7d 0a 20 20 20 20 20 20 65 6e 61 62 6c 65 28 74 }. enable(t
05e0 72 75 65 29 3b 0a 20 20 20 20 7d 3b 0a 20 20 20 rue);. };.
05f0 20 73 65 6e 64 2e 6f 6e 63 6c 69 63 6b 20 3d 20 send.onclick =
0600 66 75 6e 63 74 69 6f 6e 28 29 20 7b 0a 20 20 20 function() {.
0610 20 20 20 69 66 20 28 21 77 73 29 20 72 65 74 75 if (!ws) retu
0620 72 6e 3b 0a 20 20 20 20 20 20 6c 6f 67 2e 69 6e rn;. log.in
0630 6e 65 72 48 54 4d 4c 20 2b 3d 20 27 53 45 4e 54 nerHTML += 'SENT
0640 3a 20 27 20 2b 20 6d 65 73 73 61 67 65 2e 76 61 : ' + message.va
0650 6c 75 65 20 2b 20 27 3c 62 72 2f 3e 27 3b 0a 20 lue + '<br/>';.
0660 20 20 20 20 20 77 73 2e 73 65 6e 64 28 6d 65 73 ws.send(mes
0670 73 61 67 65 2e 76 61 6c 75 65 29 3b 0a 20 20 20 sage.value);.
0680 20 7d 0a 20 20 3c 2f 73 63 72 69 70 74 3e 0a 3c }. </script>.<
0690 2f 68 74 6d 6c 3e 0a /html>.
1c2bb5 2 sock.c:112:iolog
-- 4 127.0.0.1:8000 <- 127.0.0.1:59668 526
0000 47 45 54 20 2f 77 65 62 73 6f 63 6b 65 74 20 48 GET /websocket H
0010 54 54 50 2f 31 2e 31 0d 0a 48 6f 73 74 3a 20 6c TTP/1.1..Host: l
0020 6f 63 61 6c 68 6f 73 74 3a 38 30 30 30 0d 0a 43 ocalhost:8000..C
0030 6f 6e 6e 65 63 74 69 6f 6e 3a 20 55 70 67 72 61 onnection: Upgra
0040 64 65 0d 0a 50 72 61 67 6d 61 3a 20 6e 6f 2d 63 de..Pragma: no-c
0050 61 63 68 65 0d 0a 43 61 63 68 65 2d 43 6f 6e 74 ache..Cache-Cont
0060 72 6f 6c 3a 20 6e 6f 2d 63 61 63 68 65 0d 0a 55 rol: no-cache..U
0070 73 65 72 2d 41 67 65 6e 74 3a 20 4d 6f 7a 69 6c ser-Agent: Mozil
0080 6c 61 2f 35 2e 30 20 28 58 31 31 3b 20 4c 69 6e la/5.0 (X11; Lin
0090 75 78 20 61 72 6d 76 37 6c 29 20 41 70 70 6c 65 ux armv7l) Apple
00a0 57 65 62 4b 69 74 2f 35 33 37 2e 33 36 20 28 4b WebKit/537.36 (K
00b0 48 54 4d 4c 2c 20 6c 69 6b 65 20 47 65 63 6b 6f HTML, like Gecko
00c0 29 20 52 61 73 70 62 69 61 6e 20 43 68 72 6f 6d ) Raspbian Chrom
00d0 69 75 6d 2f 37 38 2e 30 2e 33 39 30 34 2e 31 30 ium/78.0.3904.10
00e0 38 20 43 68 72 6f 6d 65 2f 37 38 2e 30 2e 33 39 8 Chrome/78.0.39
00f0 30 34 2e 31 30 38 20 53 61 66 61 72 69 2f 35 33 04.108 Safari/53
0100 37 2e 33 36 0d 0a 55 70 67 72 61 64 65 3a 20 77 7.36..Upgrade: w
0110 65 62 73 6f 63 6b 65 74 0d 0a 4f 72 69 67 69 6e ebsocket..Origin
0120 3a 20 68 74 74 70 3a 2f 2f 6c 6f 63 61 6c 68 6f : http://localho
0130 73 74 3a 38 30 30 30 0d 0a 53 65 63 2d 57 65 62 st:8000..Sec-Web
0140 53 6f 63 6b 65 74 2d 56 65 72 73 69 6f 6e 3a 20 Socket-Version:
0150 31 33 0d 0a 41 63 63 65 70 74 2d 45 6e 63 6f 64 13..Accept-Encod
0160 69 6e 67 3a 20 67 7a 69 70 2c 20 64 65 66 6c 61 ing: gzip, defla
0170 74 65 2c 20 62 72 0d 0a 41 63 63 65 70 74 2d 4c te, br..Accept-L
0180 61 6e 67 75 61 67 65 3a 20 7a 68 2d 43 4e 2c 7a anguage: zh-CN,z
0190 68 3b 71 3d 30 2e 39 0d 0a 53 65 63 2d 57 65 62 h;q=0.9..Sec-Web
01a0 53 6f 63 6b 65 74 2d 4b 65 79 3a 20 61 69 6a 63 Socket-Key: aijc
01b0 35 31 35 71 66 7a 79 56 5a 78 64 45 79 76 31 63 515qfzyVZxdEyv1c
01c0 44 77 3d 3d 0d 0a 53 65 63 2d 57 65 62 53 6f 63 Dw==..Sec-WebSoc
01d0 6b 65 74 2d 45 78 74 65 6e 73 69 6f 6e 73 3a 20 ket-Extensions:
01e0 70 65 72 6d 65 73 73 61 67 65 2d 64 65 66 6c 61 permessage-defla
01f0 74 65 3b 20 63 6c 69 65 6e 74 5f 6d 61 78 5f 77 te; client_max_w
0200 69 6e 64 6f 77 5f 62 69 74 73 0d 0a 0d 0a indow_bits....
1c2bb6 2 sock.c:112:iolog
-- 4 127.0.0.1:8000 -> 127.0.0.1:59668 129
0000 48 54 54 50 2f 31 2e 31 20 31 30 31 20 53 77 69 HTTP/1.1 101 Swi
0010 74 63 68 69 6e 67 20 50 72 6f 74 6f 63 6f 6c 73 tching Protocols
0020 0d 0a 55 70 67 72 61 64 65 3a 20 77 65 62 73 6f ..Upgrade: webso
0030 63 6b 65 74 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e cket..Connection
0040 3a 20 55 70 67 72 61 64 65 0d 0a 53 65 63 2d 57 : Upgrade..Sec-W
0050 65 62 53 6f 63 6b 65 74 2d 41 63 63 65 70 74 3a ebSocket-Accept:
0060 20 4d 75 47 51 2f 53 4b 56 35 58 6d 34 77 76 4e MuGQ/SKV5Xm4wvN
0070 4c 69 34 71 55 68 52 77 37 6c 6b 63 3d 0d 0a 0d Li4qUhRw7lkc=...
0080 0a .
1c5be6 2 sock.c:112:iolog
-- 4 127.0.0.1:8000 <- 127.0.0.1:59668 18
0000 81 8c ed 7f 06 db a5 1a 6a b7 82 5f 51 b4 9f 13 ........j.._Q...
0010 62 fa b.
1c5be7 2 sock.c:112:iolog
-- 4 127.0.0.1:8000 -> 127.0.0.1:59668 14
0000 81 0c 48 65 6c 6c 6f 20 57 6f 72 6c 64 21 ..Hello World!
可以看到整个操作过程的收发消息都打印了出来。
另外我们也可以使用 Mongoose 的 websocket-client 示例程序来访问我们的 WebSocket 服务器。
【参考资料】
examples/websocket-server
Documentation
rfc6455
本文链接:https://blog.csdn.net/u012028275/article/details/128513876