You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派GTK GUI gsocket服务器读取数据需客户端断开问题排查

问题分析与解决方案

你的问题根源非常明确:g_data_input_stream_read_line_async是专门用来读取「一行数据」的API——它会一直阻塞等待,直到捕获到换行符(或者输入流被主动关闭)才会触发完成回调。

从你给出的输出和Wireshark抓包结果来看,客户端发送的二进制数据0 5 0 4 0 1 0 1 0 6 0 0 0 7并没有携带换行符,所以服务器的异步读操作会一直卡在等待状态,直到客户端断开连接(此时输入流结束),才会把收到的所有数据当成"一行"返回。

解决思路(二选一即可)

方案1:让客户端发送数据后追加换行符

如果你的Demo允许修改客户端逻辑,最简单的方法就是让客户端在发送完目标数据后,额外发送一个换行符(\n或\r\n)。这样read_line_async在捕获到换行符后会立即触发回调,不需要等客户端断开连接。

方案2:改用按长度读取的异步API(更适合二进制数据场景)

如果你的数据是二进制格式(像你给出的十六进制数据),按行读取本身就不是合适的选择。推荐改用g_data_input_stream_read_async来读取指定长度的数据,或者循环读取直到流结束。

下面是修改后的核心代码示例:

static void on_input_read_finish(GObject *object, GAsyncResult *result, gpointer user_data) {
    GDataInputStream *gis = G_DATA_INPUT_STREAM(object);
    guchar *buffer;
    gsize bytes_read = 0;
    GError *error = NULL;

    g_print("before g_data_input_stream_read_finish\n");
    buffer = g_data_input_stream_read_finish(gis, result, &bytes_read, &error);
    
    if (error) {
        g_print("Read error: %s\n", error->message);
        g_error_free(error);
        g_object_unref(gis);
        return;
    }

    if (bytes_read > 0) {
        g_print("after g_data_input_stream_read_finish\n");
        g_print("bytes read: %zu\n", bytes_read);
        for (gsize i = 0; i < bytes_read; i++) {
            g_print("%x ", buffer[i]);
        }
        g_print("\n");
        g_free(buffer);

        // 如果需要持续接收客户端的后续数据,在这里再次发起异步读
        g_data_input_stream_read_async(gis, 14, G_PRIORITY_DEFAULT, NULL, on_input_read_finish, NULL);
    } else {
        // 客户端断开连接,释放资源
        g_print("Client disconnected\n");
        g_object_unref(gis);
    }
}

gboolean sockconnectionestablished(GSocketService *sockservice, GSocketConnection *connection, GObject *source_object, gpointer user_Data) {
    g_print("socket connection established!\n");
    GDataInputStream *gis = g_data_input_stream_new(g_io_stream_get_input_stream(G_IO_STREAM(connection)));
    g_print("after g_data_input_stream_new\n");

    // 发起异步读取,这里假设我们每次读取14字节(和你收到的数据长度一致)
    // 如果数据长度不固定,可以先读取长度字段,再读取对应数据
    g_data_input_stream_read_async(gis, 14, G_PRIORITY_DEFAULT, NULL, on_input_read_finish, NULL);
    g_print("after g_data_input_stream_read_async\n");
    return TRUE;
}

额外提示

  • 若需要持续接收客户端的后续数据,一定要在回调函数里再次调用g_data_input_stream_read_async,否则只会读取一次数据。
  • 记得处理读取错误和流结束的情况,避免内存泄漏。
  • 如果你确实需要用按行读取的逻辑,一定要确保客户端发送的数据包含换行符,你已经设置的G_DATA_STREAM_NEWLINE_TYPE_ANY可以兼容多种换行格式,这部分是没问题的。

内容的提问来源于stack exchange,提问作者jollymonrogers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:20:12