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

C语言null结尾字符串转非null结尾及UDP收发挂起问题求助

问题诊断与修复方案

核心问题定位

你遇到的程序挂起问题,核心是以下几个代码逻辑错误导致的:

  • IP地址合法性错误:你提供的ip_address数组中存在大量非法IP,比如879.120.8.249(IP段最大值为255,879超出范围)、85.195.823.169(823超出范围)。inet_addr处理非法IP时会返回INADDR_NONE(值为0xffffffff),你直接将无效地址赋值给目标地址结构,会导致sendto发送异常,后续recvfrom永远收不到返回报文直接阻塞。你硬编码IP时运行正常,正是因为硬编码的是合法可达的IP,避开了这个问题。
  • 字符串处理逻辑错误:你不需要额外做null结尾转非null结尾的操作,inet_addr本身要求输入为null结尾的C字符串。你当前的address栈空间只申请了l字节,却用memcpy拷贝了l+1字节(包含末尾的\0),直接造成栈溢出,破坏栈上的servaddr、socket文件描述符等变量,引发未知错误。
  • socket使用逻辑错误:
    1. 你使用MSG_WAITALL标志调用recvfrom,默认会无限阻塞直到收到完整报文,只要目标IP不可达、端口未监听、网络丢包都会直接导致程序挂起。
    2. 代码中每次循环末尾都会执行close(sockfd),如果sockfd是在循环外创建的,第一次循环结束后文件描述符就已经失效,后续循环的收发操作都会直接报错。
  • buffer遍历越界风险:你判断buffer[i]==62 && buffer[i-1]==62时,当i=0会访问buffer[-1],属于非法内存读,会破坏程序运行数据。

具体修复步骤

  1. 过滤非法IP:每次调用inet_addr后增加返回值校验,非法IP直接跳过当前循环:
servaddr.sin_addr.s_addr = inet_addr(ip_address[k]);
if (servaddr.sin_addr.s_addr == INADDR_NONE) {
    printf("第%d个IP %s 非法,跳过\n", k, ip_address[k]);
    continue;
}
  1. 删除冗余的字符串转换代码:直接将ip_address[k]传入inet_addr即可,不需要额外申请address变量做转换。
  2. 给socket设置接收超时,避免无限阻塞:在创建socket后添加超时配置:
// 设置3秒接收超时
struct timeval tv = {.tv_sec = 3, .tv_usec = 0};
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
  1. 调整socket创建/关闭逻辑:要么把socket()调用放到循环内部,每次循环创建新的socket;要么把close(sockfd)移到整个循环结束之后执行。
  2. 修复buffer遍历逻辑:循环从i=1开始,避免越界访问:
int len=0;
for(i=1;i<MAXLINE;i++){
    len++;
    if(buffer[i]==62 && buffer[i-1]==62)
        break;  
}
  1. 所有系统调用增加错误判断:sendto、recvfrom调用后判断返回值,出错直接打印perror快速定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 14:48:00