从struct sockaddr获取IP地址不适用于32位编译

时间:2011-05-11 00:05:39

标签: c linux networking ip 32bit-64bit

我有一个小型客户端/服务器应用程序,用于发送/接收UDP发现数据包。收到UDP数据包时,我想显示源IP。客户端/服务器代码基于Beej的UDP示例:https://beej.us/guide/bgnet/html/multi/clientserver.html

当我编译为64位时,IP会按预期显示,但是当我编译为32位(-m32选项)时,它根本没有得到正确的值。

代码snippit:

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

...

printf("listener: waiting to recvfrom...\n");
addr_len = sizeof their_addr;
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
    (struct sockaddr *)their_addr, &addr_len)) == -1) {
    perror("recvfrom");
    exit(1);
}

printf("listener: got packet from %s\n",
    inet_ntop(their_addr->sa_family,
        get_in_addr((struct sockaddr *)their_addr),
        s, sizeof s));

printf("Sockaddr: ");
for (i=0; i<sizeof(struct sockaddr_in); i++)
    printf("%x ", ((char *)their_addr)[i]);
printf("\n");

编译为64位时更正输出:

    listener: waiting to recvfrom...
    listener: got packet from 192.168.20.6
    Sockaddr: 2 0 ffffff80 19 ffffffc0 ffffffa8 14 6 64 2e 40 0 0 0 0 0 

使用-m32:

编译时输出错误
    listener: waiting to recvfrom...
    listener: got packet from 168.32.140.255
    Sockaddr: 2 0 ffffff80 19 ffffffa8 20 ffffff8c ffffffff 50 ffffffdd 7d fffffff7 4 0 0 0 

我真的不明白为什么在编译32位时使用get_in_addr或inet_ntop会出现问题?

3 个答案:

答案 0 :(得分:3)

addr_len应设置为地址结构的大小,而不是指针的大小(它发生在64位模式下,因为指针在该模式下是两倍大)。所以它应该是:

addr_len = sizeof *their_addr;

顺便提一下,their_addr如何初始化?必须有一个真实的结构指向。

答案 1 :(得分:2)

除了错误之外,这是一种处理IP地址的方法。您应该使用带有getnameinfo标志的NI_NUMERICHOST来获得可呈现的地址形式。那么你不必关心它是v4还是v6,甚至是v7或v8。

答案 2 :(得分:0)

get_in_addr不是标准函数。很可能你的实现错了。显示代码。