树莓派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
相关产品推荐
相关产品推荐

