空间里怎么放多个网站,国外用wordpress,有没有专做烘焙的网站,医疗服务网站素材方法是libuv用多事件循环来驱动。说起来容易#xff0c;做起来还是比下面的方法更容易#xff1a; 上图是某位网友的方法代表子大部分网络资料。此方法对部署不友好#xff0c;因为软件仓库提供的libwebsockets是不能用了。如何简化部署#xff0c;利用好现有的软件仓库呢做起来还是比下面的方法更容易 上图是某位网友的方法代表子大部分网络资料。此方法对部署不友好因为软件仓库提供的libwebsockets是不能用了。如何简化部署利用好现有的软件仓库呢
libwebsockets版本历史
libwebsockets曾经是无缝支持libuv的。不过随着版本号的增大它对libuv的支持越来越差了。首先快速回顾下libwebsockets的版本历史
v0.1.0 - 2011年9月这是libwebsockets的第一个版本它提供了基本的WebSocket协议支持包括创建WebSocket连接、发送和接收消息等基本功能。v0.2.0 - 2012年1月这个版本添加了对HTTP协议的支持使得libwebsockets可以处理HTTP请求和响应。此外还添加了对多线程的支持使得你可以在多个线程中安全地使用libwebsockets。v0.3.0 - 2012年7月这个版本添加了对SSL/TLS加密的支持使得你可以使用安全连接来传输WebSocket消息。此外还添加了一些新的API和功能比如定时器和回调函数等。v0.4.0 - 2013年1月这个版本添加了对HyBi-17协议的支持这是WebSocket协议的一个扩展版本提供了更多的功能和更好的性能。此外还修复了一些已知的漏洞和错误。v0.5.0 - 2014年2月这个版本添加了对多路复用和支持这意味着你可以同时处理多个WebSocket连接。此外还添加了一些新的API和功能比如获取连接信息、处理文件上传等。v1.0.0 - 2015年9月这是libwebsockets的一个重要版本它标志着libwebsockets已经成熟并稳定。这个版本添加了对HTTP/2协议的支持同时优化了性能和内存使用。此外还修复了一些已知的漏洞和错误。v1.1.0 - 2016年3月这个版本主要修复了一些已知的漏洞和错误同时添加了一些新的功能和优化比如更好的日志记录和内存管理。v2.0.0 - 2018年8月这是一个具有里程碑意义的版本它引入了许多新的功能和改变。其中包括更好的多线程支持、对更多协议的支持如Raw WebSocket、HyBi-17、HTTP等以及对更多操作系统的支持。此外它还改进了API设计并修复了许多已知问题。v2.1.0 - 2019年4月这个版本主要修复了一些已知的漏洞和错误同时添加了一些新的功能和优化比如更好的SSL/TLS支持和对更多操作系统的支持。v3.0.0 - 2020年5月这个版本标志着libwebsockets进入了一个新的阶段。它引入了更多新的功能和改变包括更好的多线程支持、对更多协议的支持如Raw WebSocket、HyBi-17、HTTP等以及对更多操作系统的支持。此外它还改进了API设计并修复了许多已知问题。从这个版本开始事件循环对libuv的支持逐渐边缘化。
关键问题
从v3.0.0开始lws_uv_initloop函数不存在。lws_context_create_info.options增加LWS_SERVER_OPTION_LIBUV导致lws_service函数崩溃。
复现问题的常规操作 编译时开启LIBUV支持在编译libwebsockets库时需要开启LIBUV支持并指定LIBUV的目录位置。这可以通过修改CMakeLists.txt文件来实现。具体来说需要在CMakeLists.txt文件中添加以下行 option(WITH_LIBUV Enable libuv support ON)
find_package(libuv REQUIRED)
include_directories(${LIBUV_INCLUDE_DIRS})
link_directories(${LIBUV_LIBRARY_DIRS})
add_definitions(-DLIBUV_SUPPORT1)这将启用LIBUV支持并自动搜索和链接LIBUV库。 修改线程模型libwebsockets默认使用自己的线程模型但可以使用libuv的线程模型替代。这需要在初始化libwebsockets时指定使用libuv线程模型。具体来说需要在调用lws_create_context函数时将thread_mode参数设置为LWS_THREAD_MODE_UV。例如 struct lws_context_creation_info info;
memset(info, 0, sizeof(info));
info.port 8000;
info.protocols protocols;
info.thread_mode LWS_THREAD_MODE_UV; // 使用libuv线程模型
struct lws_context *context lws_create_context(info);这将告诉libwebsockets使用libuv的线程模型进行初始化。 使用libuv的API在使用libwebsockets时需要使用libuv提供的API来进行读写操作和事件处理。例如可以使用uv_read_start和uv_write_t等函数来进行读写操作使用uv_run函数来进行事件循环。这些函数将在libuv库中提供。例如 uv_stream_t *stream;
uv_buf_t buf;
uv_read_start(stream, on_read, buf); // 开始读取操作
uv_write(req, stream, buf.base, nread, on_write); // 开始写入操作
uv_run(uv_default_loop(), UV_RUN_DEFAULT); // 运行事件循环解决思路
每个线程一个循环。可以在同一线程中使用多个事件循环。但这通常没有意义因为一个循环的 uv_run() 调用将阻止并停止另一个循环的运行。通过仔细组合 uv_run(loop, UV_RUN_ONCE) 你可以做一些非常有趣的事情。您可以使用多个循环在程序中创建“模态”步骤其中第二个事件循环“暂停”第一个事件循环直到发生某些操作用户按 Return 键或您收到新事件或其他事件。
有一个非常具体的用例可以使用两个事件循环作为同步机制来代替条件变量。当时 libuv 没有条件变量支持现在我保持这种方式以允许它与早期的节点版本一起使用。具体用例是
主线程使用 uv_queue_work() 在工作线程中调用阻塞函数。工作线程必须调用自定义函数。问题是自定义函数必须在主线程上运行。工作线程必须等待该函数返回。
条件变量方法是
工作线程不直接调用自定义函数。相反它创建一个 uv_async_t 处理程序。此处理程序的回调调用自定义函数。初始化条件变量。它使用 uv_async_send() 来让主线程事件循环运行的地方代表它调用该函数。等待条件变量。回调调用自定义函数然后向条件变量发出信号让工作线程继续运行。
事件循环实现改为
在工作线程中创建一个新的事件循环。将 uv_async_t 与这个新循环关联起来。通过原始 uv_async_t 处理程序的数据字段将此处理程序传递到主线程。uv_run() 新的事件循环现在会阻塞因为异步处理程序已经增加了它的 refcount 。主线程中的回调调用自定义函数然后使用 uv_async_send() 向新循环上的异步处理程序发出信号。该异步处理程序的回调只是关闭处理程序本身新循环的引用计数降至零uv_run() 返回并且工作线程可以继续。
解决办法
下面的示例由TCP服务和websockets服务组成。TCP服务只是一个echo服务端websockets则是静态文件服务仅两个网页index.html和404.html。
TCP线程
void tcp_thread_cb(void* args)
{uv_loop_t loop;uv_loop_init(loop);struct sockaddr_in addr;uv_tcp_t server;int ierr uv_tcp_init(loop, server);VOID_RETURN(ierr);ierr uv_ip4_addr(0.0.0.0, IPORT, addr);VOID_RETURN(ierr);ierr uv_tcp_bind(server, (const struct sockaddr*)addr, 0);VOID_RETURN(ierr);ierr uv_listen((uv_stream_t*)server, 128, on_new_connection);VOID_RETURN(ierr);printf(server started.\n);ierr uv_run(loop, UV_RUN_DEFAULT);VOID_RETURN(ierr);uv_stop(loop);uv_barrier_wait((uv_barrier_t*)args);
}websockets线程
void websockets_thread_cb(void* args)
{static struct lws_context* context;static const struct lws_http_mount mounts[] { {/* .mount_next */ NULL, /* linked-list next *//* .mountpoint */ /, /* mountpoint URL *//* .origin */ ., /* serve from dir *//* .def */ index.html, /* default filename *//* .protocol */ NULL,/* .cgienv */ NULL,/* .extra_mimetypes */ NULL,/* .interpret */ NULL,/* .cgi_timeout */ 0,/* .cache_max_age */ 0,/* .auth_mask */ 0,/* .cache_reusable */ 0,/* .cache_revalidate */ 0,/* .cache_intermediaries */ 0,/* .origin_protocol */ LWSMPRO_FILE, /* files in a dir *//* .mountpoint_len */ 1, /* char count *//* .basic_auth_login_file */ NULL,},{0,} };struct lws_context_creation_info info { 0, };lws_set_log_level(LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE, NULL);info.port 20001;info.mounts mounts;info.error_document_404 /404.html;info.options LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE;context lws_create_context(info);assert(context);lwsl_user(websockets started\n);while (1)lws_service(context, 0);lws_context_destroy(context);uv_barrier_wait((uv_barrier_t*)args);
}主函数
int main(int argc, char** argv)
{uv_loop_t* loop uv_default_loop();uv_thread_t t[2];uv_barrier_t b;uv_barrier_init(b, 3);int ierr uv_thread_create(t[0], tcp_thread_cb, b);RAISE_RETURN(ierr);ierr uv_thread_create(t[1], websockets_thread_cb, b);RAISE_RETURN(ierr);ierr uv_run(loop, UV_RUN_DEFAULT);RAISE_RETURN(ierr);uv_barrier_wait(b);return 0;
}通用部分
#include uv.h
#include libwebsockets.h
#include stdio.h
#include malloc.h
#include assert.h#define RAISE_RETURN(x) \if((x)) \{ \fprintf(stderr, error {%s} code %ld %s\n, __func__, (long int)(x), uv_strerror(x)); \printf(error {%s} code %ld %s\n, __func__, (long int)(x), uv_strerror(x)); \raise(x); \return (x); \}
#define VOID_RETURN(x) \if((x)) \{ \fprintf(stderr, error {%s} code %ld %s\n, __func__, (long int)(x), uv_strerror(x)); \printf(error {%s} code %ld %s\n, __func__, (long int)(x), uv_strerror(x)); \return; \}验证
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 作者岬淢箫声日期2023年11月7日版本1.0链接http://caowei.blog.csdn.net