在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是相同的数字!
答案 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
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()
函数中声明的参数。