什么关心参数sizeof(sockaddr_in)

时间:2015-02-04 09:47:55

标签: c assembly

connect()函数中,最后一个参数是sockaddr_in结构的大小。

好吧,但是sin_zero未使用(系统没有像我在stackoverflow.com/questions/28280581/how-kernels-recognize-sin-zero-sockaddr-in-structure-pushed中所理解的那样“弹出sin_zero”),那么函数需要这个参数呢?

即。 asm或当C编译为asm时,connect()的RET必须指定要删除的字节数(RET n),即connect()参数的字节。为什么n是一个固定的数字(不要改变我指定sin_zero或否)如果我可以在asm中推送或没有sin_zero并在C中为sin_zero赋值。如果我在asm中创建一个程序而且我不推送sin_zero在堆栈中,程序运行完美......但是n是相同的数字!

3 个答案:

答案 0 :(得分:1)

sockaddr_in是包含互联网地址的结构。该结构在<netinet/in.h>中定义。这是服务器/客户端地址struct sockaddr_in serv_addr, cli_addr;这是定义:

struct sockaddr_in {
    short   sin_family;
    u_short sin_port;
    struct  in_addr sin_addr;
    char    sin_zero[8];
};

sin_family - 使用AF_INET sin_port - 端口号(网络字节顺序=&gt;使用htons(port)sin_addr - struct in_addr

描述的Internet地址
struct in_addr {
        unsigned long s_addr;
};

s_addr设为INADDR_ANY =&gt;本地互联网地址。 sin_zero[] - 设置为0 bzero()memset()。填充以使结构与SOCKADDR的大小相同。

bind()示例

int mysock,err;
struct sockaddr_in myaddr; 
mysock = socket(AF_INET,SOCK_STREAM,0);
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons( portnum );
myaddr.sin_addr.s_addr = INADDR_ANY;
bzero(&(myaddr.sin_zero),sizeof(myaddr.sin_zero));
err = bind(mysock, (struct sockaddr *) &myaddr, sizeof(myaddr));

我找到了一些关于sin_zero(Unix网络编程3.2章)

的信息
  

POSIX规范在结构中只需要三个成员:sin_family,sin_addr和sin_port。符合POSIX的实现可以定义其他结构成员,这对于Internet套接字地址结构来说是正常的。几乎所有实现都添加了sin_zero成员,以便所有套接字地址结构的大小至少为16个字节。

sin_zero

的定义
unsigned char  __pad[__SOCK_SIZE__ - sizeof(short int)
                    - sizeof(unsigned short int) - sizeof(struct in_addr)];
};
#define sin_zero        __pad
  

大多数网络代码不使用sockaddr_in,它使用sockaddr。当您使用像sendto这样的函数时,您必须将sockaddr_in或您使用的任何地址显式地转换为sockaddr。 sockaddr_in与sockaddr的大小相同,但内部大小相同,因为有轻微的黑客攻击。

那个黑客是sin_zero。实际上sockaddr_in中有用数据的长度比sockaddr短。但是使用一个小缓冲区在sockaddr_in中填充差异;缓冲区是sin_zero。

在某些架构上,它不会导致任何不清除sin_zero的问题。但在其他架构上它可能会。规范要求清除sin_zero,所以如果你打算现在和将来你的代码都没有bug,你必须这样做。

请看一下page

答案 1 :(得分:0)

我认为,内核使用size参数来查看你的sockaddr是否是ipv6地址,因为ipv6地址大小比linux和unix中的其他网址大。

答案 2 :(得分:0)

可能是架构问题,在sockaddr_in中声明的64位/ 32位大小的原语在不同的架构上会有所不同。这就是为什么它可能是connect()函数中声明的参数。