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期望接收字符串指针,程序会将该整数值当作内存地址去读取字符串,几乎必然访问到非法内存地址,直接触发段错误。- 其他潜在问题:
client.sin_port是网络字节序的端口值,直接用%d打印会得到错误的端口号,需要用ntohs()转为本地字节序再打印。void main()不符合C语言标准,标准写法为int main(),执行结束返回0表示正常退出。error()是GNU扩展函数,需要额外引入<error.h>头文件,更通用的错误打印方案是使用标准库的perror()。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
相关产品推荐
相关产品推荐

