2026/3/28 21:36:38
网站建设
项目流程
网上做网站兼职,网站加载特效代码,站点推广名词解释,百度做公司网站GSocketService 是 GLib/GIO 库中的一个核心类#xff0c;用于简化异步网络服务或本地套接字服务的创建。它工作在 GLib 的主事件循环上#xff0c;能高效地处理并发连接。
#x1f9e9; GSocketService 核心解读
你可以通过下面的表格快速了解它的关键特性#xff1a;
…GSocketService是 GLib/GIO 库中的一个核心类用于简化异步网络服务或本地套接字服务的创建。它工作在 GLib 的主事件循环上能高效地处理并发连接。 GSocketService 核心解读你可以通过下面的表格快速了解它的关键特性特性维度具体说明核心角色一个在GLib 主循环上运行的套接字监听器用于接受传入连接。继承关系继承自GSocketListener需使用父类方法如add_inet_port绑定地址和端口。线程模型本身不是线程安全的运行在创建它的线程的主循环中-1。但其start()和stop()方法是线程安全的。事件驱动采用异步、非阻塞模式。新连接到达时会发出incoming信号处理函数必须立即返回以避免阻塞。核心特性自动连接管理处理新的客户端连接异步 I/O基于 GIO 的异步操作非阻塞线程支持可在工作线程中处理连接多协议支持TCP, Unix domain socket️ 如何使用 GSocketService通常有两种使用方式信号连接创建服务后连接incoming信号到一个处理函数。子类化创建GSocketService的子类并重写其默认的incoming信号处理函数。一个典型的使用流程如下// 创建服务 GSocketService *service g_socket_service_new(); // 监听端口例如8080 g_socket_listener_add_inet_port(G_SOCKET_LISTENER(service), 8080, NULL, NULL); // 连接 incoming 信号 g_signal_connect(service, incoming, G_CALLBACK(on_incoming_connection), NULL); // 启动服务默认创建时已启动除非被停止过 g_socket_service_start(service); // 确保主循环运行 GMainLoop *loop g_main_loop_new(NULL, FALSE); g_main_loop_run(loop);/** * brief 创建 DBus 代理监听的套接字服务 * param socketPath 套接字路径 * return 创建成功返回 GSocketService 指针失败返回 nullptr */ GSocketService *KMDbusProxy::createSocketServer(const std::string socketPath) { if (std::error_code ec; fs::exists(socketPath, ec)) { fs::remove(socketPath, ec); } // 创建socket服务 GSocketService *service g_socket_service_new(); // 创建socket地址 GSocketAddress *address g_unix_socket_address_new(socketPath.c_str()); // 添加地址到服务 GError *error nullptr; g_socket_listener_add_address(G_SOCKET_LISTENER(service), address, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, nullptr, nullptr, error); if (error) { KMError(failed to create dbusproxy socket server: std::string(error-message)); g_error_free(error); g_object_unref(address); g_object_unref(service); return nullptr; } // 释放地址引用 g_object_unref(address); // 连接新连接信号 g_signal_connect(service, incoming, G_CALLBACK(onNewConnection), this); // 启动服务 g_socket_service_start(G_SOCKET_SERVICE(service)); return service; }关键点在incoming信号的处理函数中你只能启动对该连接的处理例如为其设置异步I/O操作不能进行阻塞操作如长时间计算或阻塞式读写。 GSocketService 与 GThreadedSocketService如果你的连接处理逻辑确实包含阻塞代码如复杂数据库查询、文件IO等应该使用其子类GThreadedSocketService。两者的主要区别如下对比项GSocketServiceGThreadedSocketService用途处理连接本身非阻塞或异步的服务。处理连接逻辑包含阻塞操作的服务。线程模型在主循环线程处理连接。为每个连接在独立的工作线程中调用run信号处理函数。处理程序要求处理函数必须立即返回。处理函数可以阻塞直到连接关闭。适用场景高并发、I/O密集型的异步服务。包含阻塞I/O或耗时计算的连接处理。创建GThreadedSocketService时可以指定线程池的最大线程数max_threads以控制并发量。 开发注意事项服务状态新创建的服务默认是活动的。只有在调用stop()停止后才需要再调用start()来重启。连接对象管理incoming信号返回后传入的GSocketConnection对象的引用计数会被减少。如果需要在信号返回后继续使用该连接必须手动调用g_object_ref()增加其引用计数。关闭监听器调用stop()只是停止接受新连接不会关闭底层监听套接字。要完全关闭需要调用从GSocketListener继承的close()方法。关键 APIGSocketService 方法g_socket_service_new()- 创建新服务g_socket_service_start()- 启动服务g_socket_service_stop()- 停止服务g_socket_service_is_active()- 检查服务是否活动GSocketListener 方法继承g_socket_listener_add_inet_port()- 监听 TCP 端口g_socket_listener_add_address()- 监听特定地址g_socket_listener_add_any_inet_port()- 监听任意可用端口信号incoming- 新连接到达时触发注意事项引用计数注意正确管理 GObject 引用计数错误处理总是检查 GError 返回值资源清理及时关闭流和释放资源线程安全如果需要跨线程访问使用线程安全的数据结构异步操作推荐使用异步 I/O 避免阻塞主循环基本使用步骤1. 创建服务GSocketService *service g_socket_service_new();2. 监听端口// TCP 监听 g_socket_listener_add_inet_port(G_SOCKET_LISTENER(service), port, NULL, error); // Unix domain socket 监听 g_socket_listener_add_address(G_SOCKET_LISTENER(service), address, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, NULL, NULL, error);3. 连接信号处理g_signal_connect(service, incoming, G_CALLBACK(on_incoming_connection), user_data);4. 启动服务g_socket_service_start(service);完整示例示例 1: 简单的 Echo 服务器#include glib.h #include gio/gio.h #include string.h #define PORT 12345 // 处理接收到的数据 static void on_data_received(GObject *source_object, GAsyncResult *res, gpointer user_data) { GInputStream *istream G_INPUT_STREAM(source_object); GOutputStream *ostream G_OUTPUT_STREAM(user_data); GError *error NULL; gchar buffer[1024]; gssize size; // 完成读取操作 size g_input_stream_read_finish(istream, res, error); if (size 0) { // 回显数据 g_output_stream_write(ostream, buffer, size, NULL, error); // 继续读取 g_input_stream_read_async(istream, buffer, sizeof(buffer), G_PRIORITY_DEFAULT, NULL, on_data_received, ostream); } else { if (error) { g_printerr(Read error: %s\n, error-message); g_error_free(error); } // 关闭连接 g_input_stream_close(istream, NULL, NULL); g_output_stream_close(ostream, NULL, NULL); g_object_unref(istream); g_object_unref(ostream); } } // 处理新连接 static gboolean on_incoming_connection(GSocketService *service, GSocketConnection *connection, GObject *source_object, gpointer user_data) { GInputStream *istream; GOutputStream *ostream; gchar buffer[1024]; g_print(New connection from client\n); // 获取输入输出流 istream g_io_stream_get_input_stream(G_IO_STREAM(connection)); ostream g_io_stream_get_output_stream(G_IO_STREAM(connection)); // 开始异步读取数据 g_input_stream_read_async(istream, buffer, sizeof(buffer), G_PRIORITY_DEFAULT, NULL, on_data_received, ostream); // 保持连接引用防止被回收 g_object_ref(connection); return TRUE; // 返回 TRUE 表示接受连接 } int main(int argc, char *argv[]) { GSocketService *service; GError *error NULL; GMainLoop *loop; // 创建 socket 服务 service g_socket_service_new(); // 监听端口 if (!g_socket_listener_add_inet_port(G_SOCKET_LISTENER(service), PORT, NULL, error)) { g_printerr(Failed to listen on port %d: %s\n, PORT, error-message); g_error_free(error); return 1; } g_print(Echo server listening on port %d\n, PORT); // 连接信号 g_signal_connect(service, incoming, G_CALLBACK(on_incoming_connection), NULL); // 启动服务 g_socket_service_start(service); // 运行主循环 loop g_main_loop_new(NULL, FALSE); g_main_loop_run(loop); // 清理 g_main_loop_unref(loop); g_object_unref(service); return 0; }示例 2: HTTP 服务器#include glib.h #include gio/gio.h #include string.h #define PORT 8080 // HTTP 响应 static const gchar *HTTP_RESPONSE HTTP/1.1 200 OK\r\n Content-Type: text/html; charsetUTF-8\r\n Content-Length: %ld\r\n \r\n htmlheadtitleTest Server/title/head bodyh1Hello from GSocketService!/h1 pCurrent time: %s/p/body/html; // 处理 HTTP 请求 static void handle_http_request(GSocketConnection *connection, const gchar *request) { GOutputStream *ostream; GDateTime *now; gchar *time_str; gchar *response_body; gchar *response; gsize response_len; GError *error NULL; // 获取当前时间 now g_date_time_new_now_local(); time_str g_date_time_format(now, %Y-%m-%d %H:%M:%S); g_date_time_unref(now); // 创建响应体 response_body g_strdup_printf(htmlbodyh1Hello!/h1pTime: %s/p pRequest: %s/p/body/html, time_str, request); g_free(time_str); // 创建完整 HTTP 响应 response_len strlen(response_body); response g_strdup_printf(HTTP_RESPONSE, response_len, response_body); // 发送响应 ostream g_io_stream_get_output_stream(G_IO_STREAM(connection)); g_output_stream_write_all(ostream, response, strlen(response), NULL, NULL, error); if (error) { g_printerr(Write error: %s\n, error-message); g_error_free(error); } // 清理 g_free(response_body); g_free(response); g_output_stream_close(ostream, NULL, NULL); g_object_unref(connection); } // 读取完整请求 static void on_request_read(GObject *source_object, GAsyncResult *res, gpointer user_data) { GInputStream *istream G_INPUT_STREAM(source_object); GSocketConnection *connection G_SOCKET_CONNECTION(user_data); GError *error NULL; gchar *buffer; gssize size; size g_input_stream_read_finish(istream, res, error); if (size 0) { buffer g_strndup((gchar*)g_bytes_get_data(g_bytes_new_static(buffer, size), NULL), size); g_print(Received request:\n%s\n, buffer); // 处理 HTTP 请求 handle_http_request(connection, buffer); g_free(buffer); } else { if (error) { g_printerr(Read error: %s\n, error-message); g_error_free(error); } g_object_unref(connection); } g_object_unref(istream); } // 处理新连接 static gboolean on_incoming_connection(GSocketService *service, GSocketConnection *connection, GObject *source_object, gpointer user_data) { GInputStream *istream; gchar buffer[4096]; g_print(New HTTP connection\n); istream g_io_stream_get_input_stream(G_IO_STREAM(connection)); // 异步读取请求 g_input_stream_read_async(istream, buffer, sizeof(buffer), G_PRIORITY_DEFAULT, NULL, on_request_read, g_object_ref(connection)); return TRUE; } int main(int argc, char *argv[]) { GSocketService *service; GError *error NULL; GMainLoop *loop; // 创建服务 service g_socket_service_new(); // 监听端口 if (!g_socket_listener_add_inet_port(G_SOCKET_LISTENER(service), PORT, NULL, error)) { g_printerr(Failed to listen on port %d: %s\n, PORT, error-message); g_error_free(error); return 1; } g_print(HTTP server listening on port %d\n, PORT); // 连接信号 g_signal_connect(service, incoming, G_CALLBACK(on_incoming_connection), NULL); // 启动服务 g_socket_service_start(service); // 运行主循环 loop g_main_loop_new(NULL, FALSE); g_main_loop_run(loop); // 清理 g_main_loop_unref(loop); g_object_unref(service); return 0; }示例 3: 带线程池的服务#include glib.h #include gio/gio.h #include string.h #define PORT 9999 #define MAX_THREADS 10 typedef struct { GSocketConnection *connection; GSocketService *service; } ThreadData; // 工作线程函数 static gpointer worker_thread(gpointer data) { ThreadData *tdata (ThreadData *)data; GInputStream *istream; GOutputStream *ostream; gchar buffer[1024]; gssize bytes_read; GError *error NULL; g_print(Thread %p handling connection\n, g_thread_self()); istream g_io_stream_get_input_stream(G_IO_STREAM(tdata-connection)); ostream g_io_stream_get_output_stream(G_IO_STREAM(tdata-connection)); // 读取数据 while ((bytes_read g_input_stream_read(istream, buffer, sizeof(buffer), NULL, error)) 0) { // 处理数据这里简单回显 g_output_stream_write(ostream, buffer, bytes_read, NULL, error); if (error) { g_printerr(Write error: %s\n, error-message); g_error_free(error); break; } } if (error) { g_printerr(Read error: %s\n, error-message); g_error_free(error); } // 清理 g_object_unref(tdata-connection); g_free(tdata); return NULL; } // 处理新连接在工作线程中处理 static gboolean on_incoming_connection(GSocketService *service, GSocketConnection *connection, GObject *source_object, gpointer user_data) { GThreadPool *pool (GThreadPool *)user_data; ThreadData *tdata; g_print(New connection, queuing for thread pool\n); // 创建线程数据 tdata g_new(ThreadData, 1); tdata-connection g_object_ref(connection); tdata-service service; // 将工作加入线程池 g_thread_pool_push(pool, tdata, NULL); return TRUE; } int main(int argc, char *argv[]) { GSocketService *service; GError *error NULL; GMainLoop *loop; GThreadPool *pool; // 创建线程池 pool g_thread_pool_new(worker_thread, NULL, MAX_THREADS, FALSE, error); if (error) { g_printerr(Failed to create thread pool: %s\n, error-message); g_error_free(error); return 1; } // 创建 socket 服务 service g_socket_service_new(); // 监听端口 if (!g_socket_listener_add_inet_port(G_SOCKET_LISTENER(service), PORT, NULL, error)) { g_printerr(Failed to listen on port %d: %s\n, PORT, error-message); g_error_free(error); return 1; } g_print(Threaded server listening on port %d\n, PORT); // 连接信号 g_signal_connect(service, incoming, G_CALLBACK(on_incoming_connection), pool); // 启动服务 g_socket_service_start(service); // 运行主循环 loop g_main_loop_new(NULL, FALSE); g_main_loop_run(loop); // 清理 g_thread_pool_free(pool, FALSE, TRUE); g_main_loop_unref(loop); g_object_unref(service); return 0; }