2011-09-27 37 views
12

我想編譯這個程序,如Beej指南中引用到網絡第19頁netdb.h中未正確連接

#include <stdio.h> 
#include <netdb.h> 
#include <sys/types.h> 
#include <sys/socket.h> 

int main() { 
    int status; 
    struct addrinfo hints; 
    struct addrinfo *servinfo;   /* Will point to the results */ 
    memset(&hints, 0, sizeof hints); /* Make sure the struct is empty */ 
    hints.ai_family = AF_UNSPEC;  /* Don't care IPv4 or IPv6 */ 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_flags = AI_PASSIVE; 

    if ((status = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0) { 
     fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status)); 
     exit(1); 
    } 

    /* Servinfo now points to a linked list of 1 or more struct addrinfos 
     ... do everything until you don't need servinfo anymore .... */ 

    freeaddrinfo(servinfo); /* Free the linked-list */ 

    return 0; 
}  

編程在其他錯誤,我看到

../main.c:8:18: error: storage size of ‘hints’ isn’t known 
../main.c:13:19: error: ‘AI_PASSIVE’ undeclared (first use in this function) 
../main.c:16:3: warning: implicit declaration of function ‘gai_strerror’ 

看來gcc沒有鏈接到netdb.h。 Eclipse,我用來構建它的IDE,沒有找到該文件的麻煩。以下是編譯器命令:

gcc -O0 -g3 -pedantic -Wall -c -fmessage-length=0 -ansi -MMD -MP -MF"main.d" -MT"main.d" -o"main.o" "../main.c" 

添加-lnetdb不能解決問題。另外...

~> find /usr/include/ -name netdb.h 
/usr/include/bits/netdb.h 
/usr/include/gssrpc/netdb.h 
/usr/include/netdb.h 
/usr/include/rpc/netdb.h 

我認爲這些文件已經預裝在我的openSUSE主機上。爲什麼gcc沒有檢測到netdb.h?或者我得出錯誤的結論?

回答

17
../main.c:8:18: error: storage size of ‘hints’ isn’t known 
../main.c:13:19: error: ‘AI_PASSIVE’ undeclared (first use in this function) 
../main.c:16:3: warning: implicit declaration of function ‘gai_strerror’ 

看來,GCC不與netdb.h中聯....

這些都不是鏈接錯誤,你不需要netdb共享對象 文件(沒有這樣的野獸; netdb.h只是簡單地定義了數據結構 和用於你的代碼的宏)。

這些編譯器錯誤:GCC抱怨,因爲你使用的名字 ,它並不能識別(AI_PASSIVE)和數據類型爲其 結構未知(struct addrinfo)。

您所呈現的代碼似乎是正確的,並且addrinfo/usr/include/netdb.h中定義。

gcc -c main.c 

你仍然得到同樣的行爲:如果你編譯它 這樣會出現什麼情況?如果是這樣,看看輸出 :

gcc -E main.c 

這生成代碼的預處理版本,所有通過其實際內容替換 #include語句。您應該 能夠通過這個給grep,看看如果編譯器實際上得到 /usr/include/netdb.h如果,如果它發現別的東西:

$ gcc -E foo.c | grep netdb.h | awk '{print $3}' | sort -u 

這在我的系統收益率:

"/usr/include/bits/netdb.h" 
"/usr/include/netdb.h" 
"/usr/include/rpc/netdb.h" 

當您添加-ansi到命令行,你正在改變方式的行爲將會破壞Linux內核和許多系統的頭文件 gcc。在netdb.haddrinfo定義保護 這樣的:

#ifdef __USE_POSIX 
/* Structure to contain information about address of a service provider. */ 
struct addrinfo 
{ 
    int ai_flags;     /* Input flags. */ 
    int ai_family;    /* Protocol family for socket. */ 
    int ai_socktype;    /* Socket type. */ 
    int ai_protocol;    /* Protocol for socket. */ 
    socklen_t ai_addrlen;   /* Length of socket address. */ 
    struct sockaddr *ai_addr;  /* Socket address for socket. */ 
    char *ai_canonname;   /* Canonical name for service location. */ 
    struct addrinfo *ai_next;  /* Pointer to next in list. */ 
}; 

// ...other stuff... 
#endif 

當您運行gcc-ansi標誌,該取消定義的 __USE_POSIX宏,因爲事情該保護可能不是 嚴格ANSI標準。你可以看到區別,如果你比較 此:

gcc -E /usr/include/netdb.h 

有了這個:

gcc -E -ansi /usr/include/netdb.h 

只有前者包含addrinfo結構。

+0

我得到與輸出相同的三個頭文件。我看到這些編譯錯誤:http://pastebin.com/jVVMqftA – Pieter

+1

所以...它的工作?也就是說,你沒有看到與'netdb.h'有關的任何錯誤,而你只是收到關於'memset()'的警告?這聽起來像是進步。 'memset()'警告意味着你需要'#include '(這來自'memset(3)'手冊頁)。 – larsks

+0

如果我還包含'string.h',我不會看到任何警告或錯誤。但是,我希望我的代碼符合ANSI C標準,因此我仍然收到這些錯誤... http://pastebin.com/B21NyGQ9 – Pieter

0

鏈接不會將頭文件附加到程序,預處理將處理頭文件。

鏈接將共享對象庫(查看/ usr/lib)附加到編譯對象。有時僅僅添加「-lnetdb」是不夠的,因爲該庫可能不在鏈接器路徑中。在這種情況下,您需要使用-L(路徑)添加路徑條目,以便指令「-lnetdb」可以找到正確的netdb.so文件。

+0

它看起來像我沒有在該文件夾中名爲'* netdb *'的共享對象... http://pastebin.com/9GPmFehC如何獲取我缺少的SO文件? – Pieter

2

添加在你的文件

#define _XOPEN_SOURCE 600 
0

使用#include <netinet/in.h>的頂部....有沿.....和編譯(Ubuntu的)....

gcc server/client -o server/client.c -lpthread 

(這裏lpthread是一個linki處理線程)...它可以解決你的問題。 :-D