C++ 实现Websocket(libwebsockets)
·
Libwebsockets(LWS)是一个灵活、轻量级的纯C库,使用非阻塞事件循环,以极小的占用空间轻松实现现代网络协议。自2010年以来,它一直在不断开发,并被全球数千万台设备和数千名开发人员使用。
uWebSockets 安装
需要先看《VCPKG 跨平台C++ 库管理器》,安装VCPKG环境之后,再来进行安装,这个需要VCKPKG C++库管理工具。
通过命令安装
vcpkg install libwebsockets


安装完毕,然后,就可以直接引用,并使用了。
示例
服务端
#include <libwebsockets.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#define MAX_PAYLOAD_SIZE 1024
static int interrupted = 0;
// 每个连接的私有数据结构(Per-Session Data)
struct per_session_data__echo {
unsigned char buf[LWS_PRE + MAX_PAYLOAD_SIZE];
size_t len;
};
// 信号处理
static void sigint_handler(int sig) {
interrupted = 1;
}
// 服务器回调函数
static int callback_echo(struct lws* wsi, enum lws_callback_reasons reason,
void* user, void* in, size_t len) {
struct per_session_data__echo* pss = (struct per_session_data__echo*)user;
switch (reason) {
case LWS_CALLBACK_RECEIVE:
if (len > MAX_PAYLOAD_SIZE) len = MAX_PAYLOAD_SIZE;
// 复制接收到的数据,注意要偏移 LWS_PRE 长度
memcpy(&pss->buf[LWS_PRE], in, len);
pss->len = len;
// 标记该连接可写,通知底层触发 WRITEABLE 回调
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
if (pss->len > 0) {
// 发送数据,指针必须指向预留了 LWS_PRE 后的位置
int n = lws_write(wsi, &pss->buf[LWS_PRE], pss->len, LWS_WRITE_TEXT);
if (n < 0) return -1;
pss->len = 0; // 清空标志,防止重复发送
}
break;
default:
break;
}
return 0;
}
// 协议列表
static struct lws_protocols protocols[] = {
{ "echo-protocol", callback_echo, sizeof(struct per_session_data__echo), MAX_PAYLOAD_SIZE, 0, NULL, 0 },
{ NULL, NULL, 0, 0, 0, NULL, 0 } /* 结束标志 */
};
int main(void) {
struct lws_context_creation_info info;
struct lws_context* context;
int n = 0;
signal(SIGINT, sigint_handler);
memset(&info, 0, sizeof(info));
info.port = 8081; // 监听端口
info.protocols = protocols; // 绑定的协议
info.gid = -1;
info.uid = -1;
context = lws_create_context(&info);
if (!context) {
lwsl_err("lws init failed\n");
return 1;
}
printf("Echo 服务器已启动,正在监听 8081 端口...\n");
// 事件循环
while (n >= 0 && !interrupted) {
n = lws_service(context, 0);
}
lws_context_destroy(context);
printf("服务器已退出\n");
return 0;
}
客户端
#include <libwebsockets.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
static int interrupted = 0;
static int client_finished = 0;
// 客户端回调函数
static int callback_client_echo(struct lws* wsi, enum lws_callback_reasons reason,
void* user, void* in, size_t len) {
switch (reason) {
case LWS_CALLBACK_CLIENT_ESTABLISHED:
printf("客户端:连接服务器成功!\n");
// 连接成功后,请求写权限以发送第一条数据
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_CLIENT_WRITEABLE: {
const char* msg = "Hello Libwebsockets Echo!";
size_t msg_len = strlen(msg);
unsigned char buf[LWS_PRE + 128];
// 必须在 LWS_PRE 之后填入数据
memcpy(&buf[LWS_PRE], msg, msg_len);
printf("客户端:发送消息 -> \"%s\"\n", msg);
lws_write(wsi, &buf[LWS_PRE], msg_len, LWS_WRITE_TEXT);
break;
}
case LWS_CALLBACK_CLIENT_RECEIVE:
// 打印收到的回显数据
printf("客户端:收到回显 <- \"%.*s\"\n", (int)len, (char*)in);
client_finished = 1; // 标记完成,准备退出循环
interrupted = 1;
break;
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
lwsl_err("客户端:连接失败\n");
interrupted = 1;
break;
default:
break;
}
return 0;
}
static struct lws_protocols protocols[] = {
{ "echo-protocol", callback_client_echo, 0, 1024, 0, NULL, 0 },
{ NULL, NULL, 0, 0, 0, NULL, 0 }
};
int main(void) {
struct lws_context_creation_info info;
struct lws_client_connect_info i;
struct lws_context* context;
int n = 0;
memset(&info, 0, sizeof(info));
info.port = CONTEXT_PORT_NO_LISTEN; // 客户端不需要监听端口
info.protocols = protocols;
context = lws_create_context(&info);
if (!context) {
lwsl_err("lws context init failed\n");
return 1;
}
// 配置连接参数
memset(&i, 0, sizeof(i));
i.context = context;
i.address = "127.0.0.1"; // 服务器 IP
i.port = 8081; // 服务器端口
i.path = "/";
i.host = i.address;
i.origin = i.address;
i.protocol = "echo-protocol"; // 必须与服务器的协议名一致
i.ssl_connection = 0; // 0 表示不使用 SSL (ws://)
if (!lws_client_connect_via_info(&i)) {
lwsl_err("Client connection failed\n");
lws_context_destroy(context);
return 1;
}
// 事件循环
while (n >= 0 && !interrupted) {
n = lws_service(context, 0);
}
lws_context_destroy(context);
return 0;
}
调试结果
先启动服务端,再启动客户端

再启动客户端

可见我们已经实现了WebSocket Server和 WebSocket Client。
更多推荐
所有评论(0)