2015-11-21 3 views
0

Я объявил struct sockaddr_in server в своей основной функции.Bind failed:: Семейство адресов не поддерживается семейством протоколов - C

я передать его в эту функцию, чтобы вернуть дескриптор файла сокета

int openSocket(char* ip_addr, int port, struct sockaddr_in* server){ 

    int sockfd, len; 

    sockfd = socket(AF_INET, SOCK_DGRAM, 0); 

    if(sockfd < 0){ 
     perror("Failed to open socket: "); 
     exit(-1); 
    } 

    len = sizeof(server); 
    bzero(server, len); 
    server->sin_family= AF_INET; 
    inet_pton(AF_INET, ip_addr, &server->sin_addr); 
    server->sin_port= htons(port); 

    if((bind(sockfd, (struct sockaddr*)&server, len)) < 0){ 
     perror("Bind failed: "); 
     exit(-1); 
    } 
    return sockfd; 

} 

структуры передаются в функцию, используя этот вызов

sockfd = openSocket(vector->ip_addr, vector->port, &server); 

Однако я получаю следующее сообщение об ошибке.

Bind failed: : Address family not supported by protocol family 

ответ

4
len = sizeof(server); 

Это определяет размер указателя. Вы хотите, чтобы размер структуры он указывает, так что это должно быть:

len = sizeof(*server); 
+0

Также 'len' должен быть' 'socklen_t' не int'. – alk

+0

@alk - Да, хорошая точка. – keithmo

3
int openSocket(char* ip_addr, int port, struct sockaddr_in* server){ 
[...] 
if((bind(sockfd, (struct sockaddr*)&server, len)) < 0){ 

server уже объявлен как указатель, так что я думаю, что & оператор не требуется в bind() вызова.

+0

Я бы использовал локальную переменную 'sockaddr_in' для' bind() 'и чтобы параметр' server' использовался только для вывода. Или просто избавитесь от параметра 'server' вообще, и если вызывающему нужно локально связанное' sockaddr_in', то он может вызывать 'getsockname()' после выхода 'openSocket()'. –

0
int openSocket(char* ip_addr, int port, struct sockaddr_in* server){ 

Это интересно - вы используете sockaddr_in, который имеет следующие свойства, необходимые для установки:

  • sun_family - Это должно равняться AF_INET.
  • sin_addr - Это еще одна структура с unsigned long именем s_addr, который вы, вероятно, хотите установить в INADDR_ANY+.
  • sin_port - Для этого требуется порт сервера, который нуждается в преобразовании с htons(). (Убедитесь, что этот порт не используется ++! Мой идти к порту 3333 для тестирования ...)

Кажется, вы используете inet_pton(), но я не уверен, что он имеет то же самое влияют на установку sin_port. Другое, что это выглядит хорошо.

Другая область там может быть проблемой является эта строка:

sockfd = socket(AF_INET, SOCK_DGRAM, 0); 

0 на концевых специфицирует [1]:

«Задание протокола 0 причин сокета() для используйте нестандартный протокол по умолчанию, соответствующий типу запрашиваемого сокета. "

Я мог представить себе, где неопределенное значение по умолчанию является неправильным для вашей операционной системы или что по умолчанию нет. Я бы попробовал SOCK_STREAM, чтобы проверить, работает ли это.

+ ПРИМЕЧАНИЕ: Это было бы технически необходимо htonl(), но я понимаю, что это ничего не делает для этого конкретного случая.

++ ПРИМЕЧАНИЕ: Если вы пишете клиентские и серверные приложения, не забывайте быть осторожными относительно того, кому принадлежит порт.

[1] http://pubs.opengroup.org/onlinepubs/009695399/functions/socket.html