C socket编程问题:实现telnet对接发送命令后仅打印一行问题排查
C语言Socket对接Telnet仅打印单行问题解决方案
核心原因定位
该异常90%以上场景由以下三类问题导致:
- Telnet协议控制字节未过滤:Telnet传输内容中会穿插IAC(值为0xFF)开头的控制信令,若程序未识别该类字节,会将其误判为文本结束标记、或是异常截断后续内容
- 接收逻辑存在缺陷:仅单次调用
recv()就结束读取流程,未处理TCP流的粘包拆包特性,也未循环拉取内核缓冲区的剩余数据 - 行结束符识别逻辑错误:Telnet标准行结束符为CRLF(
\r\n),若程序仅以\n作为行分割标记,部分返回内容会被识别为单行长文本,或是出现回车符覆盖已有打印内容的异常,视觉上呈现为仅打印一行
修复方案
1. 新增Telnet控制字节过滤逻辑
读取字节时若检测到IAC控制标记,直接跳过对应控制序列,不纳入文本处理:
// Telnet文本读取函数,自动过滤控制信令 int telnet_read(int sockfd, char* out_buf, int buf_max_len) { int write_pos = 0; char tmp_byte; while (write_pos < buf_max_len - 1) { int ret = recv(sockfd, &tmp_byte, 1, 0); if (ret <= 0) return ret; // 处理Telnet IAC控制序列 if (tmp_byte == 0xFF) { // 读取命令字节 recv(sockfd, &tmp_byte, 1, 0); // 带参数的控制命令需要多跳过一个字节 if (tmp_byte >= 0xFB && tmp_byte <= 0xFE) { recv(sockfd, &tmp_byte, 1, 0); } continue; } out_buf[write_pos++] = tmp_byte; // 可选:按行读取时读到换行符即可返回,不需要按行读取可删除该判断 if (tmp_byte == '\n') break; } out_buf[write_pos] = '\0'; return write_pos; }
2. 修正接收循环逻辑
持续调用读取函数直到连接断开,不要单次读取就终止流程:
char recv_buffer[1024]; int read_len; while ((read_len = telnet_read(sock_fd, recv_buffer, sizeof(recv_buffer))) > 0) { printf("%s", recv_buffer); memset(recv_buffer, 0, sizeof(recv_buffer)); }
3. 统一行结束符处理
将读取到的\r\n序列统一替换为\n,避免回车符导致的打印内容被覆盖问题。
校验方法
- 打印所有接收字节的十六进制值,确认是否存在未过滤的Telnet控制字节,以及行结束符格式是否符合预期
- 打印每次
recv()调用的返回值,确认是否存在单次读取未拉取全量数据的问题
内容的提问来源于stack exchange,提问作者RamEir
相关产品推荐
相关产品推荐

