gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 15:59:59 27 4
gpt4 key购买 nike

我正在学习使用 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 传递给 watch 回调。

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;
}

你没有在 watch 回调 network_read() 中返回,你必须以“return true”结束它。来自文档:“如果应该删除事件源,函数应该返回 FALSE”。

100% 的 CPU 是由于在连接关闭时 channel 仍然存在的事实造成的。确保在不再需要时正确删除事件源。

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;
}

关于c - 需要帮助使用 GIOService(GLib、Glib-GIO)实现简单的套接字服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2417681/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com