Linux C Socket服务端与Telnet客户端数据传输异常问题求助
问题原因及解决方法
问题根因梳理
1. 无法进入if (bytes_index > 0)代码块的核心原因
accept的第三个参数client_len未初始化:accept要求调用前必须将该参数设置为传入的地址结构体长度,否则会导致accept执行异常,后续收数据逻辑完全出错。- 换行处理逻辑有漏洞:仅在检测到行尾是
\r时才给input赋值\0,如果收到的换行符不带\r,input就不是合法的C字符串,后续字符串操作会越界;且当输入的行没有\r时,处理完换行后bytes_index的值等于有效内容长度,若内容长度为1,bytes_index会变为0,无法满足>0的判断条件。 - 打印语句参数类型错误触发段错误:用
%s格式化输出input[0]这类单个字符,%s要求传入char*类型的字符串首地址,传入字符值会被当成非法内存地址,直接导致程序崩溃,自然看不到代码块内的输出。
2. bytes_index取值不符合预期的原因
- 未处理
recv返回0的异常分支:当客户端断开连接时recv返回0,此时会直接break退出收数据循环,bytes_index会停在异常递增后的值,不符合业务预期。 - 换行处理的计数逻辑有漏洞:处理
\n时直接bytes_index--,但没有考虑无\r的场景下的计数修正,导致有效长度统计错误。 - 原
accept报错打印缺少参数:代码中fprintf(stderr, "accept failed with error %d\n");没有传入错误值参数,会输出垃圾值干扰问题排查。
修复方案
1. 初始化必要参数,修正accept错误打印
在accept调用前添加client_len初始化,同时补全报错打印参数:
client_len = sizeof(struct sockaddr_in); cfd = accept(rfd, (struct sockaddr *) &client, &client_len); if (cfd < 0) { fprintf(stderr, "accept failed with error %d\n", cfd); exit(-1); }
2. 修正换行处理逻辑,统一补字符串结束符
将收数据循环内的换行处理逻辑修改为:
if (input[bytes_index] == '\n') { // 先把\n替换成结束符 input[bytes_index] = '\0'; // 再处理\r的情况 bytes_index--; if (bytes_index >=0 && input[bytes_index] == '\r') { input[bytes_index] = '\0'; } break; }
3. 修正判断条件和打印语句
- 将
if (bytes_index > 0)改为if (bytes_index >= 0 && strlen(input) > 0),避免短内容被过滤。 - 打印单个字符的语句将
%s改为%c:
printf("%c\n", input[0]); //G printf("%c\n", input[1]); //e printf("%c\n", input[2]); //t
4. 添加缓冲区溢出防护
在收数据循环内增加判断,避免bytes_index超过BUFSIZE-1,防止数组越界:
while (1) { // 新增缓冲区满判断 if (bytes_index >= BUFSIZE -1) { input[BUFSIZE-1] = '\0'; break; } bytes_read = recv(cfd, &input[++bytes_index], 1, 0); // 原有逻辑不变 if (bytes_read <= 0) break; // 原有换行处理逻辑不变 }
内容的提问来源于stack exchange,提问作者user12595983
相关产品推荐
相关产品推荐

