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

C语言编写UDP监听套接字调用recvfrom出现段错误如何解决

问题原因分析

导致段错误的核心原因有两个,还有几处潜在的不规范写法:

  • recvfrom的长度参数未初始化
    int clientlen;仅定义未赋值,recvfrom的最后一个参数是输入输出参数,调用前必须初始化为传入的地址结构体的缓冲区大小,即clientlen = sizeof(struct sockaddr_in)。未初始化的clientlen是随机栈值,可能导致recvfrom向client结构体写入时溢出栈内存,触发段错误。
  • printf格式符严重不匹配
    client.sin_addr.s_addr是32位无符号整数(存储网络字节序的IP地址),但你使用%s格式符打印它。%s期望接收字符串指针,程序会将该整数值当作内存地址去读取字符串,几乎必然访问到非法内存地址,直接触发段错误。
  • 其他潜在问题:
    1. client.sin_port是网络字节序的端口值,直接用%d打印会得到错误的端口号,需要用ntohs()转为本地字节序再打印。
    2. void main()不符合C语言标准,标准写法为int main(),执行结束返回0表示正常退出。
    3. error()是GNU扩展函数,需要额外引入<error.h>头文件,更通用的错误打印方案是使用标准库的perror()。
    4. close()函数需要引入<unistd.h>头文件,inet_ntoa()(用于转换IP为点分十进制字符串)需要引入<arpa/inet.h>头文件。
修复后的完整代码
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>

int main() {
    struct sockaddr_in server;
    struct sockaddr_in client;
    socklen_t clientlen;
    char buf[1500];

    int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sock < 0) {
        perror("ERROR on socket create");
        return 1;
    }

    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    server.sin_port = htons(9090);

    if(bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {
        perror("ERROR on binding");
        return 1;
    }

    while(1) {
        memset(buf, 0, 1500);
        clientlen = sizeof(client);
        recvfrom(sock, buf, 1500-1, 0, (struct sockaddr *) &client, &clientlen);
        printf("%s\n", buf);
        printf("%d - %s\n", ntohs(client.sin_port), inet_ntoa(client.sin_addr));
    }
    close(sock);
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 09:24:04