getnameinfo指定socklen_t

时间:2010-05-04 12:15:03

标签: c linux networking posix socklen-t

getnameinfo原型的第二个arg请求socklen_t类型,但sizeof使用size_t。那我怎么能得到socklen_t?

原型:

int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
       char *restrict node, socklen_t nodelen, char *restrict service,
       socklen_t servicelen, int flags);

示例:

struct sockaddr_in SIN;
memset(&SIN, 0, sizeof(SIN)); // This should also be socklen_t ?
SIN.sin_family      = AF_INET;
SIN.sin_addr.s_addr = inet_addr(IP);
SIN.sin_port        = 0;

getnameinfo((struct sockaddr *)&SIN, sizeof(SIN) /* socklen_t */, BUFFER, NI_MAXHOST, NULL, 0, 0);

这会给编译器错误:

socklen_t VAR;
getnameinfo((struct sockaddr *)&SIN, &VAR, BUFFER, NI_MAXHOST, NULL, 0, 0);

3 个答案:

答案 0 :(得分:9)

size_t is defined作为无符号整数类型; C99保证它至少为16位。

socklen_t is defined作为至少32位的整数类型。 (编辑:它不一定是无符号的,但在实践中,负长度将毫无意义。)

所以传递一个size_t参数并让编译器隐式地将它转换为socklen_t没有问题,我认为这会让你的代码更清晰,让隐式转换发生而不是添加迂腐管型。

你的最后一个例子

socklen_t VAR;
getnameinfo((struct sockaddr *)&SIN, &VAR, BUFFER, NI_MAXHOST, NULL, 0, 0);

给出了一个编译器错误,因为你传递的指针指向socken_t而不是socklen_t。

答案 1 :(得分:1)

您的信息已过期,socklen_t是一个至少32位(http://www.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html)的整数类型(不一定是无符号)。

答案 2 :(得分:0)

(这是this IMHO falsely duplicate-tagged question试图触及socklen_t存在底部的答案。)

正如其他人所指出的,可以将其视为POSIX套接字API的size_t等价物,它表示各种数据结构的长度(以字节为单位)。最值得注意的是bind()listen()connect()函数,它表示struct sockaddr的各种实现的长度,但并不仅限于此。< / p>

POSIX specification实际上解释了它如何成为并且非常有启发性恕我直言:

  

类型socklen_t的发明是为了涵盖该领域的实现范围。 socklen_t的意图是所有长度自然有限的类型;也就是说,它们是一个缓冲区的长度,它不能合理地变成大尺寸:网络地址,主机名,这些的字符串表示,辅助数据,控制消息和套接字选项都是例子。真正的无限大小由size_t表示,如read()write(),依此类推。

     

所有socklen_t类型最初(在BSD UNIX中)类型为int。在开发POSIX.1-2008期间,决定将所有缓冲区长度更改为size_t,这在面值处显示有意义。当双模式32/64位系统出现时,这种选择会不必要地使系统接口变得复杂,因为size_t(带有long)在ILP32和LP64模型下的大小不同。恢复到int会发生,除了一些实现已经发布了64位接口。妥协是一种类型,可以通过实现定义为任何大小:socklen_t