2011-09-27 38 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