2013-09-17 4 views
2

Я пишу небольшую программу сокетов, которая привязана только к указанному ip: port, но bind() не удалось, если struct sockaddr_in не является bzero и gcc с опцией -O2.Socket bind failed на sockaddr_in без bzero

Вот коды:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 
#include <arpa/inet.h> 
#include <netinet/tcp.h> 

int main(int argc, char **argv){ 
    struct sockaddr_in addr; 
    //bzero(&addr, sizeof(addr)); 
    addr.sin_family = AF_INET; 
    addr.sin_port = htons((unsigned short)9009); 
    inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr); 

    int sock; 
    if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1){ 
     perror("socket error"); 
     exit(0); 
    } 
    if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1){ 
     printf("socket error: %d, %s\n", errno, strerror(errno)); 
     exit(0); 
    } 

    return 0; 
} 

Обратите внимание bzero(&addr, sizeof(addr)); закомментирован, я намерен парафировать sockadd_in каждого члена. Компиляция и запуск:

$ gcc a.c; ./a.out 
OK 

$ gcc -O2 a.c; ./a.out 
socket error: 49, Can't assign requested address 

Мы знаем, что структура sockadd_in определяется как:

struct in_addr { 
    in_addr_t s_addr;   /* 32-bit IPv4 address */ 
           /* network byte ordered */ 
}; 

struct sockaddr_in { 
    uint8_t   sin_len;  /* length of structure (16) */ 
    sa_family_t  sin_family; /* AF_INET */ 
    in_port_t  sin_port;  /* 16-bit TCP or UDP port number */ 
           /* network byte ordered */ 
    struct in_addr sin_addr;  /* 32-bit IPv4 address */ 
           /* network byte ordered */ 
    char   sin_zero[8]; /* unused */ 
}; 

Мой вопрос, имеет ли привязка() реализация зависит от sockaddr_in.sin_zero очищаются?

Edit: Mac OS X, Darwin Kernel Version 12.4.0 X86_64

+2

Я бы рекомендовал распечатать значение errno, когда сбой не выполняется. Это должно сказать нам немного больше об отказе. –

+1

Я не могу воспроизвести вашу проблему (запущенная программа в цикле несколько тысяч раз). Однако структура очистки является хорошей практикой, особенно когда вы уже столкнулись с ошибкой один раз. – keltar

+2

Вы не устанавливаете поле «sin_len». Я бы это исправил и повторил. – EJP

ответ

1

правила, используемые в связывания имен варьируются в разных семействах адресов. и есть также это поле sin_zero в struct sockaddr_in, которое, как утверждают некоторые люди, должно быть установлено равным нулю. Другие люди ничего не заявляют об этом (документация Linux даже не упоминает об этом), и есть другая документация, в которой утверждается, что sin_zero был удален из struct sockaddr_in, Я пробовал как с комментарием bzero, так и с комментариями , Прокомментированный работает хорошо некоторое время в локальной сети, но некомментированная версия работает все время в локальной сети или нет. поэтому я думаю, что bzeroing - хорошая практика.

+0

POSIX не документирует никакой 'sin_zero'; он только позволяет 'sockaddr_in' иметь дополнительные элементы рядом со стандартными тремя. – Kaz

Смежные вопросы