需要帮助使用 GIOService(GLib、Glib-GIO)实现简单的套接字服务器

2023-12-09

我正在学习使用 GLib 编写简单、高效的套接字服务器的基础知识。我正在尝试 GSocketService。到目前为止,我似乎只能接受连接,但随后它们立即关闭。从文档中我无法弄清楚我错过了哪一步。我希望有人能为我阐明这一点。

运行以下命令时:

# telnet localhost 4000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
# telnet localhost 4000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
# telnet localhost 4000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.

服务器的输出:

# ./server
New Connection from 127.0.0.1:36962
New Connection from 127.0.0.1:36963
New Connection from 127.0.0.1:36965

当前代码:

/*
 * server.c
 *
 *  Created on: Mar 10, 2010
 *      Author: mark
 */
#include <glib.h>
#include <gio/gio.h>

gchar *buffer;

gboolean
network_read(GIOChannel *source,
            GIOCondition cond,
            gpointer data)
{
  GString *s = g_string_new(NULL);
  GError *error;
  GIOStatus ret = g_io_channel_read_line_string(source, s, NULL, &error);
  if (ret == G_IO_STATUS_ERROR)
    g_error ("Error reading: %s\n", error->message);
  else
    g_print("Got: %s\n", s->str);

}

gboolean
new_connection(GSocketService *service,
              GSocketConnection *connection,
              GObject *source_object,
              gpointer user_data)
{
  GSocketAddress *sockaddr = g_socket_connection_get_remote_address(connection, NULL);
  GInetAddress *addr = g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(sockaddr));
  guint16 port = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(sockaddr));

  g_print("New Connection from %s:%d\n", g_inet_address_to_string(addr), port);

  GSocket *socket = g_socket_connection_get_socket(connection);

  gint fd = g_socket_get_fd(socket);
  GIOChannel *channel = g_io_channel_unix_new(fd);
  g_io_add_watch(channel, G_IO_IN, (GIOFunc) network_read, NULL);
  return TRUE;
}

int main(int argc, char **argv) {
  g_type_init();
  GSocketService *service = g_socket_service_new();
  GInetAddress *address = g_inet_address_new_from_string("127.0.0.1");
  GSocketAddress *socket_address = g_inet_socket_address_new(address, 4000);
  g_socket_listener_add_address(G_SOCKET_LISTENER(service), socket_address, G_SOCKET_TYPE_STREAM,
          G_SOCKET_PROTOCOL_TCP, NULL, NULL, NULL);

  g_object_unref(socket_address);
  g_object_unref(address);
  g_socket_service_start(service);

  g_signal_connect(service, "incoming", G_CALLBACK(new_connection), NULL);

  GMainLoop *loop = g_main_loop_new(NULL, FALSE);
  g_main_loop_run(loop);
}

必须在传入回调中引用 GSocketConnection,这将使连接保持活动状态。您可以将其传递给数据结构、类,或作为 user_data 传递给监视回调。

gboolean
new_connection(...)
{
  ...

  g_object_ref (connection);
  GSocket *socket = g_socket_connection_get_socket(connection);

  gint fd = g_socket_get_fd(socket);
  GIOChannel *channel = g_io_channel_unix_new(fd);
  // Pass connection as user_data to the watch callback
  g_io_add_watch(channel, G_IO_IN, (GIOFunc) network_read, connection);
  return TRUE;
}

您不会在手表回调 network_read() 中返回,您必须以“return true”结束。从文档中:“如果应删除事件源,该函数应返回 FALSE".

100% CPU 使用率是由于连接关闭时通道仍处于活动状态所致。确保在不再需要时正确删除事件源。

gboolean
network_read(GIOChannel *source,
             GIOCondition cond,
             gpointer data)
{
  GString *s = g_string_new(NULL);
  GError *error = NULL;
  GIOStatus ret = g_io_channel_read_line_string(source, s, NULL, &error);

  if (ret == G_IO_STATUS_ERROR) {
    //g_error ("Error reading: %s\n", error->message);
    g_warning ("Error reading: %s\n", error->message);
    // Drop last reference on connection
    g_object_unref (data);
    // Remove the event source
    return FALSE;
  }
  else
    g_print("Got: %s\n", s->str);

  if (ret == G_IO_STATUS_EOF) {
    return FALSE;
  }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

需要帮助使用 GIOService(GLib、Glib-GIO)实现简单的套接字服务器 的相关文章

随机推荐

  • Git - 如何查看方法/函数的更改历史记录?

    所以我发现了关于如何查看文件的更改历史记录的问题 但是这个特定文件的更改历史记录是巨大的 我真的只对特定方法的更改感兴趣 那么是否可以查看该特定方法的更改历史记录 我知道这需要 git 来分析代码 并且不同语言的分析会有所不同 但方法 函数
  • 尝试从应用扩展访问钥匙串时出现“没有可用钥匙串”错误

    我正在制作一个 IOS 自定义键盘扩展 默认情况下 键盘的功能有限 但是当用户从主父应用程序购买完整版本时 键盘会解锁缺少的部分 为了检查用户是否购买了该应用程序 我尝试存储Bool在 IOS 钥匙串中使用这个图书馆 let IAPKeyc
  • UTF8 和日语字符

    问题 外来字符未按应有的方式显示 这包括德语 日语 俄语和除英语之外的所有其他语言 完美运行 PHP 通过 jQuery AJAX 调用调用 MySQL 它应该返回信息并将其显示在页面上 数据被调用并显示 然而 对于非英语字符 结果显示为
  • 如何根据 iFrame 内容的大小“增长”iFrame?

    我正在动态加载 iFrame 有些页面比其他页面 更高 我希望 iFrame 能够相应地增长 是否可以 如果是这样 怎么办 是的 jquery 是可以的 父页面代码 iframe页面上的脚本 function alertSize var m
  • 如何实现网页的实时更新?

    Google 的 GMail 服务之所以能做到这一点 是因为它集成了 Google Talk 而 Etherpad 现在的 typewith me 使 Google Wave 等使用的系统闻名 当其他用户对页面进行更改时 所有此类系统都会立
  • 禁用 LLVM 10 C++ API 的常量折叠

    我正在使用 LLVM C API 为 C 语言的子集编写编译器前端 我注意到生成的 IR 总是应用恒定的折叠优化 但我想禁用此功能并获得忠实的 未优化的 IR 有什么办法可以做到这一点吗 以下是我用来从模块生成 IR 的代码 llvm ve
  • 当通过 javascript/jquery 更改值时,多个选择不会更新

    我有一个多重选择 其中每个选项都设置了一个类 根据类别 我可以预先选择特定类别的所有选项 因此用户不必自己选择所有选项 到目前为止 它运行良好 直到我通过单击手动选择一个选项 从现在开始 预选似乎不再起作用了 但只有视觉效果不再起作用 选项
  • 使用 Youtube Iframe API 创建的视频播放器停止与 Chrome v.85 配合使用

    我在将 Youtube iframe API 与最新稳定版本的 Chrome 版本 85 一起使用时遇到问题 我知道一个月前一切都可以正常工作 但现在 即使完全遵循 Youtube iframe API 文档中找到的最基本的示例 https
  • INotifyCollectionChanged 未更新 UI

    我有一堂课 如下所示 为了简洁起见 我删除了所有功能 public class PersonCollection IList
  • 如何在部署到 Vercel 的 Next.js 应用程序中正确设置环境变量?

    我正在 Next js 中构建我的网络应用程序 并且我一直在做一些测试 我正在做的是将我的代码推送到 GitHub 然后从那里将项目部署到 Vercel 我正在使用 Google API 依赖项 它需要一些客户端 ID 和客户端密钥 以便我
  • 查找组中最常见的观察结果[重复]

    这个问题在这里已经有答案了 数据框 B pd DataFrame b II II II II II I I I MOST FREQUENT 1 2 2 1 1 1 2 2 我需要获取列中出现次数最多的值MOST FREQUENT对于每组 p
  • #[inline] 可以在特征方法声明和实现中使用吗?

    我有一些小方法的特征 这些方法通常作为实现结构所具有的其他方法的单行包装器来实现 如果我想确保特征方法是内联的 我应该放置 inline always 在特征定义内 或在impl对于每个结构 我更愿意简单地将其放入特征定义中 但据我所知 这
  • 如何将最新更改拉取到 GitHub 中我当前的工作分支?

    假设我在分支 abc test git pull origin master 这是否会将 master 分支与我当前的分支 abc test 合并 或者我是否需要运行更多命令 tl dr run git fetch获取最新更改 然后运行gi
  • 在 2.0.5 中,将 cassandra 作为服务启动不起作用,sudo cassandra -f 有效

    当我尝试在 ubuntu 12 04 上启动 cassandra 时 通过 Datastax 安装 dsc20包 作为服务如下 sudo 服务 cassandra 启动 it says 无法访问 Cassandra 的 pidfile 日志
  • 如何使用弹出窗口在 JavaScript 中构建一个简单的图片库

    我在互联网上寻找帮助 但我无法让它工作 有人能给我一个如何编写这样的代码的例子吗 我会调整图像的大小 并为弹出窗口提供一个缩略图大小的图像和一个更大的图像 我希望用户单击缩略图大小的图像并在弹出窗口中显示全尺寸的图像 我是 Javascri
  • Excel:如何使用VBA检查单元格是否为空? [复制]

    这个问题在这里已经有答案了 通过VBA 我如何检查一个单元格是否是另一个具有特定信息的空单元格 例如 如果 A A 产品特殊 且 B B 为 null 那么 C1 产品特殊 另外 我如何使用For Each循环在Range以及如何返回另一个
  • 选择不同数据库中的列

    是否可以在位于同一服务器上的不同数据库之间执行选择 或插入 语句 如果是 怎么办 您可以使用以下语法指定数据库databasename tablename Example SELECT mydatabase1 tblUsers UserID
  • 如何彻底卸载oracle 11g?

    如何从笔记本电脑上卸载 Oracle 11g 软件附带的卸载程序并不能完全卸载所有组件 我用Oracle12c试了一下 留下了很多程序 我尝试手动删除这些文件 但 BIN 目录中的某些 dll 文件无法访问 我想用 11g 做正确的事 有什
  • 使用jquery从父页面访问子IFrame中的元素

    我尝试使用以下代码从父文档访问 iframe 中文档的元素 但由于某种原因无法使其工作 父级 html
  • 需要帮助使用 GIOService(GLib、Glib-GIO)实现简单的套接字服务器

    我正在学习使用 GLib 编写简单 高效的套接字服务器的基础知识 我正在尝试 GSocketService 到目前为止 我似乎只能接受连接 但随后它们立即关闭 从文档中我无法弄清楚我错过了哪一步 我希望有人能为我阐明这一点 运行以下命令时