libwebsockets入门
WebSocket是一种在单个TCP连接上进行全双工通讯的协议,用于在Web客户端和服务器之间建立持久连接,进行实时通信。它是HTML5开始提供的一种通讯方式,通过使用WebSocket连接,web应用程序可以执行实时的交互,而不是以前的轮询方式。一个WebSocket连接是独立的TCP连接,异步的、双向的、全双工的消息传递实现机制。
特点
WebSocket具有以下特点:
- 持久连接:在HTTP协议的基础上,WebSocket实现了长连接,即服务器和客户端之间可以保持长时间的通信状态,避免了频繁建立和断开连接的开销。
- 全双工通信:WebSocket允许服务器和客户端之间任意时刻发送消息,实现了真正的双向通信。
- 协议切换:WebSocket协议在HTTP协议的基础上升级实现,兼容性良好,可以在使用同样域名和端口的情况下,升级到WebSocket协议。
- 轻量级:WebSocket的数据格式比较轻量,性能开销小,通信高效。
- 跨平台性:WebSocket可以在不同的操作系统和设备上使用,具有较好的跨平台性。
- 总的来说,WebSocket是一种高效、稳定的网络通信协议,适用于需要实时交互的Web应用程序。
发展简介
WebSocket的历史背景可以追溯到2008年,当时WebSocket协议首次被提出。自2010年开始,WebSocket得到了浏览器厂商的广泛支持,并逐渐成为Web应用程序中实现实时通信的重要技术。在此之前,虽然已经存在一些实时通信技术,但它们通常需要通过入侵现有的web技术来实现,而这些技术并不是为实时应用而设计的。
在WebSocket出现之前,web是建立在HTTP协议的基础上的,而HTTP协议最初完全是作为一种请求-响应机制设计的。这种机制在早期的web应用中表现良好,因为当时的场景只需要处理一个文本文档和一些额外的资源即可。然而,随着web应用的不断发展,对于实时通信的需求也越来越强烈,WebSocket就是在这样的背景下应运而生的。
WebSocket的出现为Internet通信创造了新的可能性,并为真正的实时通讯打开了大门。它提供了一种持久连接的方式,使得服务器和客户端之间可以保持长时间的通信状态,从而实现了真正的双向通信。同时,WebSocket也具有较好的兼容性和跨平台性,可以在不同的操作系统和设备上使用。
总之,WebSocket的历史背景是在web应用程序对于实时通信的需求不断增长的背景下产生的。它提供了一种高效、稳定的网络通信协议,适用于需要实时交互的Web应用程序。
libwebsockets
libwebsockets是一种用于C语言的轻量级网络库,它提供了为创建WebSocket服务器和客户端而编写的API。使用它可以轻松地实现WebSockets、HTTP(S)/1.1等协议。它旨在成为一个高效、灵活和可移植的解决方案。
现在由意大利的计算机科学家Salvatore Sanfilippo维护,他也是Redis数据库的创建者。
libwebsockets的优点包括:
- 轻量级:libwebsockets使用C语言编写,不需要任何附加的库或外部依赖项,非常轻量级。
- 高效性:libwebsockets旨在提供高效性和低消耗,与其他网络库相比,它的消息处理速度更快,内存开销更小。
- 可移植性:libwebsockets可以在所有主要平台上运行,包括Windows、Linux、Mac OS X等,提供了适用于多个平台的API,且易于移植到其他平台。
- 支持
ws://
和wss://
协议:libwebsockets支持ws://
和wss://
协议,可以选择和OpenSSL
、CyaSSL
或者WolfSSL
链接。 - 事件循环、零拷贝:libwebsockets支持事件循环、零拷贝等功能。
- API丰富:libwebsockets提供的API相当底层,可以实现简单的功能,对于复杂功能也提供了丰富的API支持。
- 总之,libwebsockets具有轻量级、高效性、可移植性、支持多种协议、事件循环和零拷贝等特点,是一个功能强大的网络库。
入门示例
这个示例程序创建了一个WebSocket服务器,监听端口号为8000。它使用自定义的协议echo-protocol,当接收到客户端发送的消息时,会将收到的消息原样返回。程序使用lws_create_context
创建WebSocket服务器上下文,并使用lws_service
处理WebSocket连接。最后,使用lws_context_destroy
销毁WebSocket服务器上下文。
#include <libwebsockets.h>
#include <string.h>
static int callback_echo(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {switch (reason) {case LWS_CALLBACK_ESTABLISHED: // 当新的连接建立时触发 lws_callback_on_writable(wsi);break;case LWS_CALLBACK_RECEIVE: // 当接收到客户端发送的消息时触发 // 直接将收到的消息返回给客户端 lws_write(wsi, in, len, LWS_WRITE_TEXT);break;default: break;}return 0;
}
static struct lws_protocols protocols[] = { {"echo-protocol", callback_echo, 0, 128,}, {NULL, NULL, 0, 0}// 结束标记
}
;
int main(void) {struct lws_context_creation_info info;memset(&info, 0, sizeof info);info.port = 8000;// 服务端监听的端口号 info.protocols = protocols;// 使用自定义的协议 info.gid = -1;// 不使用组ID info.uid = -1;// 不使用用户ID info.options = LWS_SERVER_OPTION_HTTP_HEADERS;// 设置选项,允许HTTP头部字段存在消息中 struct lws_context *context = lws_create_context(&info);// 创建WebSocket服务器上下文 while (1) {// 循环运行服务器,直到手动停止 lws_service(context, 50);// 处理WebSocket连接,超时时间设置为50毫秒}lws_context_destroy(context);// 销毁WebSocket服务器上下文 return 0;
}
与libuv集成
关键点是libuv的异步I/O机制中调用libwebsockets提供的方法。示例程序如下:
#include <uv.h>
#include <libwebsockets.h> static void on_read(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { struct lws *wsi = (struct lws *)stream->data; int n; if (nread < 0) { lws_close(wsi, LWS_CLOSE_STATUS_GOINGAWAY, "UV read error"); return; } if (nread == 0) return; n = lws_write(wsi, buf->base, nread, LWS_WRITE_TEXT); if (n < 0) { lws_close(wsi, LWS_CLOSE_STATUS_GOINGAWAY, "Cannot write"); return; }
} static void on_write(uv_write_t *req, int status) { struct lws *wsi = (struct lws *)req->data; if (status) { lws_close(wsi, LWS_CLOSE_STATUS_GOINGAWAY, "UV write error"); return; }
} static void service(struct lws *wsi) { uv_loop(uv_default_loop()); // 开始事件循环
} static int callback(struct lws *wsi, enum lws_callback_reasons reason) { switch (reason) { case LWS_CALLBACK_ESTABLISHED: // 当新的连接建立时触发 uv_write_t *req = (uv_write_t *)malloc(sizeof(*req)); // 创建UV写入请求对象 uv_buf_t buf = uv_buf_init((char *)"Hello, client!", 13); // 创建缓冲区对象,存储要写入的消息内容 uv_write(req, (uv_stream_t *)&wsi->stream, &buf, 1, NULL); // 向客户端写入消息,并关联回调函数on_write和请求对象req req->data = wsi; // 将请求对象关联到WebSocket连接对象wsi上,方便后续处理请求时获取wsi对象 break; case LWS_CALLBACK_RECEIVE: // 当接收到客户端发送的消息时触发 // 处理接收到的消息,这里只是简单地打印消息内容到控制台 printf("Received message: %s\n", (char *)in); break; default: // 其他情况处理,例如连接关闭等操作可以在这里处理 break; } return 0; // 返回0表示处理成功,否则表示处理失败,会触发回调函数on_close或on_error等操作
}
作者: | 岬淢箫声 |
日期: | 2023年11月7日 |
版本: | 1.0 |
链接: |
libwebsockets入门
WebSocket是一种在单个TCP连接上进行全双工通讯的协议,用于在Web客户端和服务器之间建立持久连接,进行实时通信。它是HTML5开始提供的一种通讯方式,通过使用WebSocket连接,web应用程序可以执行实时的交互,而不是以前的轮询方式。一个WebSocket连接是独立的TCP连接,异步的、双向的、全双工的消息传递实现机制。
特点
WebSocket具有以下特点:
- 持久连接:在HTTP协议的基础上,WebSocket实现了长连接,即服务器和客户端之间可以保持长时间的通信状态,避免了频繁建立和断开连接的开销。
- 全双工通信:WebSocket允许服务器和客户端之间任意时刻发送消息,实现了真正的双向通信。
- 协议切换:WebSocket协议在HTTP协议的基础上升级实现,兼容性良好,可以在使用同样域名和端口的情况下,升级到WebSocket协议。
- 轻量级:WebSocket的数据格式比较轻量,性能开销小,通信高效。
- 跨平台性:WebSocket可以在不同的操作系统和设备上使用,具有较好的跨平台性。
- 总的来说,WebSocket是一种高效、稳定的网络通信协议,适用于需要实时交互的Web应用程序。
发展简介
WebSocket的历史背景可以追溯到2008年,当时WebSocket协议首次被提出。自2010年开始,WebSocket得到了浏览器厂商的广泛支持,并逐渐成为Web应用程序中实现实时通信的重要技术。在此之前,虽然已经存在一些实时通信技术,但它们通常需要通过入侵现有的web技术来实现,而这些技术并不是为实时应用而设计的。
在WebSocket出现之前,web是建立在HTTP协议的基础上的,而HTTP协议最初完全是作为一种请求-响应机制设计的。这种机制在早期的web应用中表现良好,因为当时的场景只需要处理一个文本文档和一些额外的资源即可。然而,随着web应用的不断发展,对于实时通信的需求也越来越强烈,WebSocket就是在这样的背景下应运而生的。
WebSocket的出现为Internet通信创造了新的可能性,并为真正的实时通讯打开了大门。它提供了一种持久连接的方式,使得服务器和客户端之间可以保持长时间的通信状态,从而实现了真正的双向通信。同时,WebSocket也具有较好的兼容性和跨平台性,可以在不同的操作系统和设备上使用。
总之,WebSocket的历史背景是在web应用程序对于实时通信的需求不断增长的背景下产生的。它提供了一种高效、稳定的网络通信协议,适用于需要实时交互的Web应用程序。
libwebsockets
libwebsockets是一种用于C语言的轻量级网络库,它提供了为创建WebSocket服务器和客户端而编写的API。使用它可以轻松地实现WebSockets、HTTP(S)/1.1等协议。它旨在成为一个高效、灵活和可移植的解决方案。
现在由意大利的计算机科学家Salvatore Sanfilippo维护,他也是Redis数据库的创建者。
libwebsockets的优点包括:
- 轻量级:libwebsockets使用C语言编写,不需要任何附加的库或外部依赖项,非常轻量级。
- 高效性:libwebsockets旨在提供高效性和低消耗,与其他网络库相比,它的消息处理速度更快,内存开销更小。
- 可移植性:libwebsockets可以在所有主要平台上运行,包括Windows、Linux、Mac OS X等,提供了适用于多个平台的API,且易于移植到其他平台。
- 支持
ws://
和wss://
协议:libwebsockets支持ws://
和wss://
协议,可以选择和OpenSSL
、CyaSSL
或者WolfSSL
链接。 - 事件循环、零拷贝:libwebsockets支持事件循环、零拷贝等功能。
- API丰富:libwebsockets提供的API相当底层,可以实现简单的功能,对于复杂功能也提供了丰富的API支持。
- 总之,libwebsockets具有轻量级、高效性、可移植性、支持多种协议、事件循环和零拷贝等特点,是一个功能强大的网络库。
入门示例
这个示例程序创建了一个WebSocket服务器,监听端口号为8000。它使用自定义的协议echo-protocol,当接收到客户端发送的消息时,会将收到的消息原样返回。程序使用lws_create_context
创建WebSocket服务器上下文,并使用lws_service
处理WebSocket连接。最后,使用lws_context_destroy
销毁WebSocket服务器上下文。
#include <libwebsockets.h>
#include <string.h>
static int callback_echo(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {switch (reason) {case LWS_CALLBACK_ESTABLISHED: // 当新的连接建立时触发 lws_callback_on_writable(wsi);break;case LWS_CALLBACK_RECEIVE: // 当接收到客户端发送的消息时触发 // 直接将收到的消息返回给客户端 lws_write(wsi, in, len, LWS_WRITE_TEXT);break;default: break;}return 0;
}
static struct lws_protocols protocols[] = { {"echo-protocol", callback_echo, 0, 128,}, {NULL, NULL, 0, 0}// 结束标记
}
;
int main(void) {struct lws_context_creation_info info;memset(&info, 0, sizeof info);info.port = 8000;// 服务端监听的端口号 info.protocols = protocols;// 使用自定义的协议 info.gid = -1;// 不使用组ID info.uid = -1;// 不使用用户ID info.options = LWS_SERVER_OPTION_HTTP_HEADERS;// 设置选项,允许HTTP头部字段存在消息中 struct lws_context *context = lws_create_context(&info);// 创建WebSocket服务器上下文 while (1) {// 循环运行服务器,直到手动停止 lws_service(context, 50);// 处理WebSocket连接,超时时间设置为50毫秒}lws_context_destroy(context);// 销毁WebSocket服务器上下文 return 0;
}
与libuv集成
关键点是libuv的异步I/O机制中调用libwebsockets提供的方法。示例程序如下:
#include <uv.h>
#include <libwebsockets.h> static void on_read(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { struct lws *wsi = (struct lws *)stream->data; int n; if (nread < 0) { lws_close(wsi, LWS_CLOSE_STATUS_GOINGAWAY, "UV read error"); return; } if (nread == 0) return; n = lws_write(wsi, buf->base, nread, LWS_WRITE_TEXT); if (n < 0) { lws_close(wsi, LWS_CLOSE_STATUS_GOINGAWAY, "Cannot write"); return; }
} static void on_write(uv_write_t *req, int status) { struct lws *wsi = (struct lws *)req->data; if (status) { lws_close(wsi, LWS_CLOSE_STATUS_GOINGAWAY, "UV write error"); return; }
} static void service(struct lws *wsi) { uv_loop(uv_default_loop()); // 开始事件循环
} static int callback(struct lws *wsi, enum lws_callback_reasons reason) { switch (reason) { case LWS_CALLBACK_ESTABLISHED: // 当新的连接建立时触发 uv_write_t *req = (uv_write_t *)malloc(sizeof(*req)); // 创建UV写入请求对象 uv_buf_t buf = uv_buf_init((char *)"Hello, client!", 13); // 创建缓冲区对象,存储要写入的消息内容 uv_write(req, (uv_stream_t *)&wsi->stream, &buf, 1, NULL); // 向客户端写入消息,并关联回调函数on_write和请求对象req req->data = wsi; // 将请求对象关联到WebSocket连接对象wsi上,方便后续处理请求时获取wsi对象 break; case LWS_CALLBACK_RECEIVE: // 当接收到客户端发送的消息时触发 // 处理接收到的消息,这里只是简单地打印消息内容到控制台 printf("Received message: %s\n", (char *)in); break; default: // 其他情况处理,例如连接关闭等操作可以在这里处理 break; } return 0; // 返回0表示处理成功,否则表示处理失败,会触发回调函数on_close或on_error等操作
}
作者: | 岬淢箫声 |
日期: | 2023年11月7日 |
版本: | 1.0 |
链接: |