Подтвердить что ты не робот

Netdb.h не правильно связывается

Я пытаюсь скомпилировать эту программу, как указано в Beej Guide to Network Programming на стр. 19.

#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? Или я делаю неправильный вывод?

4b9b3361

Ответ 1

../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 в командную строку, вы меняете способ gcc ведет себя так, как это может нарушить ядро ​​Linux и многие системы файлы заголовков. Определение addrinfo в netdb.h защищено например:

#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.

Ответ 2

добавить в начало файла

#define _XOPEN_SOURCE 600

Ответ 3

Связывание не прикрепляет файл заголовка к программе, предварительная обработка обрабатывает файлы заголовков.

Связывание прикрепляет общие библиотеки объектов (смотрите/usr/lib) к скомпилированным объектам. Иногда не достаточно просто добавить "-lnetdb", поскольку библиотека, возможно, не находится в пути компоновщика. В этом случае вам нужно использовать -L (путь), чтобы добавить запись пути, чтобы директива "-lnetdb" могла найти правильный файл netdb.so.

Ответ 4

Используйте #include <netinet/in.h>.... вместе с тем..... и в компиляции (ubuntu)....

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

(здесь lpthread - поток обработки linki)... который решает вашу проблему.:-D