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

使用GSocketClient对接Telnet时g_input_stream_read_all()阻塞如何解决

问题根因

你出现阻塞的核心原因是误用了g_input_stream_read_all()接口:

  • 该接口的设计逻辑是必须读满你传入的指定字节数(你代码里是1024),或者遇到流结束、IO错误时才会返回,只要TCP连接还存活,且服务端没有发送够1024字节数据,接口就会一直阻塞等待数据到达。
  • Telnet服务端默认是行缓冲输出,大部分场景下不会一次性发送满1024字节的数据,所以你读完第一个恰好满1024字节的块之后,下一次调用g_input_stream_read_all()就会进入无限等待,直到连接断开触发流结束才返回。

解决方案

把g_input_stream_read_all()替换为g_input_stream_read()即可,该接口不会等待凑满指定字节数,只要内核接收缓冲区有可用数据就会返回,返回值即为本次实际读到的字节数,返回0代表对端关闭了连接,返回-1代表出现IO错误。

修改后的参考代码如下:

GInputStream* istream = g_io_stream_get_input_stream(G_IO_STREAM(scon));
GOutputStream* ostream = g_io_stream_get_output_stream(G_IO_STREAM(scon));

gssize dlen = 0;
gchar buffer[1024];
GError* error = NULL;

// 改用g_input_stream_read,有多少读多少
while ((dlen = g_input_stream_read(istream, buffer, 1024, NULL, &error)) > 0) {
    for (int i = 0; i < dlen; i++) {
        g_print("%c", buffer[i]);
    }
}

if (error != NULL) {
    // 错误处理逻辑
    g_print("读取错误:%s\n", error->message);
    g_error_free(error);
}

额外注意事项

  • 如果你是在GTK UI线程中执行上述读取逻辑,同步读仍然会阻塞UI主循环导致界面无响应,建议改用g_input_stream_read_async()异步IO接口,通过回调处理到达的数据,不会阻塞主线程。
  • Telnet协议包含特殊的IAC控制指令,直接打印可能会出现乱码,若要做完整的Telnet客户端需要额外处理协议控制字节。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 07:12:06