2011-05-11 61 views
1

我有一個發送/接收UDP發現數據包的小型客戶端/服務器應用程序。當收到一個UDP數據包時,我想顯示源IP。該客戶端/服務器代碼是基於來自Beej的UDP示例:http://beej.us/guide/bgnet/output/html/multipage/clientserver.html從struct sockaddr獲取IP地址不適用於32位編譯

當我編譯爲64位時,IP按預期方式顯示,但當我編譯爲32位(-m32選項)時,它沒有得到正確的值所有。

代碼片段:當使用-m32編譯

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 

錯誤輸出:

// 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 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會出現問題?

回答

2

addr_len應該設置爲地址結構的大小,而不是指針的大小(它發生在64位模式下工作,因爲指針在該模式下是兩倍大)。所以它應該是:

addr_len = sizeof *their_addr; 

順便說一句,their_addr如何初始化?必須有一個真正的結構指向。

+0

謝謝,那確實是我的問題!正確設置'addr_len'使代碼適用於64位和32位。 – austinmarton 2011-05-11 00:37:10

0

get_in_addr不是標準功能。很可能你的實現是錯誤的。顯示代碼。

+0

你是對的我已經盲目地複製它,然後認爲這是一個標準功能。已編輯原始帖子。 – austinmarton 2011-05-11 00:31:06

2

除了這些錯誤之外,這是處理IP地址的一種方式。您應該使用getnameinfoNI_NUMERICHOST標誌來獲得可呈現的地址形式。那麼你不必關心它是v4還是v6,甚至v7或v8。