没有bzero的sockaddr_in上的套接字绑定失败

时间:2013-09-17 05:23:53

标签: c sockets bind

我编写了一个只绑定到指定ip:port的小套接字程序,但是如果struct sockaddr_in不是bzero且gcc带有选项-O2,则bind()失败。

以下是代码:

#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

我们可以知道struct 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 */
};

我的问题是,bind()实现是否依赖sockaddr_in.sin_zero被清除?

编辑:Mac OS X,Darwin内核版本12.4.0 X86_64

1 个答案:

答案 0 :(得分:1)

名称绑定中使用的规则因地址系列而异。并且在struct sockaddr_in中也有这个sin_zero字段,有些人声称必须将其设置为零。其他人对它没有任何要求(Linux文档根本没有提到它),还有其他文档声称sin_zero已从struct sockaddr_in中删除,  我试过用bzero评论和未评论。评论在本地网络中运行良好,但未评论的版本无论是否在本地网络中都有效。所以我猜bzeroing是一种很好的做法。