[英]What additional purpose can ai_protocol serve in hints while calling getaddrinfo() when ai_socktype is already specified?
The getaddrinfo accepts struct addrinfo *hints
as the third argument which can be used to specify the criteria for selecting socket addresses to be returned by this function. getaddrinfo接受
struct addrinfo *hints
作为第三个参数,该参数可用于指定选择此函数返回的套接字地址的标准。
The documentation says that we could set ai_socktype
as well as ai_protocol
to specify our selection criteria.文档说我们可以设置
ai_socktype
和ai_protocol
来指定我们的选择标准。 However, I am unable to understand why ai_protocol
is required if we already specify ai_socktype
.然而,我无法理解为什么
ai_protocol
如果我们已经指定需要ai_socktype
。 If one of these two is specified, then the other seems redundant.如果指定了这两个中的一个,那么另一个似乎是多余的。
Here is some code that I wrote to experiment with this.这是我写的一些代码来试验这个。
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
void getaddrinfo_demo(const char *node, const char *service,
int socktype, int protocol)
{
struct addrinfo hints, *res, *p;
int error;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = socktype;
hints.ai_protocol = protocol;
error = getaddrinfo(node, service, &hints, &res);
if (error) {
printf("Error %d: %s\n\n", error, gai_strerror(error));
return;
}
for (p = res; p != NULL; p = p->ai_next) {
struct sockaddr_in *addr = ((struct sockaddr_in *) p->ai_addr);
char ip[INET_ADDRSTRLEN];
int port = ntohs(addr->sin_port);
inet_ntop(AF_INET, &addr->sin_addr, ip, INET_ADDRSTRLEN);
printf("ip: %s; port: %d; protocol: %d\n", ip, port, p->ai_protocol);
}
printf("\n");
freeaddrinfo(res);
}
int main()
{
/* Consistent family and socktype works fine. */
getaddrinfo_demo("localhost", "http", SOCK_STREAM, IPPROTO_TCP);
getaddrinfo_demo("localhost", "http", SOCK_DGRAM, IPPROTO_UDP);
/* Inconsistent family and sock type leads to error -7. */
getaddrinfo_demo("localhost", "http", SOCK_STREAM, IPPROTO_UDP);
getaddrinfo_demo("localhost", "http", SOCK_DGRAM, IPPROTO_TCP);
}
Here is the output.这是输出。
$ gcc -std=c99 -D_POSIX_SOURCE -Wall -Wextra -pedantic foo.c && ./a.out
ip: 127.0.0.1; port: 80; protocol: 6
ip: 127.0.0.1; port: 80; protocol: 6
ip: 127.0.0.1; port: 80; protocol: 17
ip: 127.0.0.1; port: 80; protocol: 17
Error -7: ai_socktype not supported
Error -7: ai_socktype not supported
As you can see if ai_socktype = AF_STREAM
, then only ai_protocol = IPPROTO_TCP
works.如您所见,如果
ai_socktype = AF_STREAM
,则只有ai_protocol = IPPROTO_TCP
有效。 Specifying ai_protocol = IPPROTO_UDP
leads to error.指定
ai_protocol = IPPROTO_UDP
会导致错误。 One might as well omit specifying ai_protocol
in the hints
if we can't specify any additional selection criteria via it.如果我们不能通过
ai_protocol
指定任何额外的选择标准,我们ai_protocol
在hints
省略指定ai_protocol
。
So what is really the role of ai_protocol
in hints
?那么
ai_protocol
在hints
真正作用是什么? Can you give an example in which ai_socktype
and ai_protocol
both serve some purpose?你能举一个例子,说明
ai_socktype
和ai_protocol
都有什么用途吗?
How about these:这些怎么样:
getaddrinfo_demo("localhost", "http", SOCK_STREAM, IPPROTO_SCTP);
getaddrinfo_demo("localhost", "imap", SOCK_STREAM, IPPROTO_TCP);
getaddrinfo_demo("localhost", "imap", SOCK_STREAM, IPPROTO_SCTP);
getaddrinfo_demo("localhost", "sbcap", SOCK_STREAM, IPPROTO_SCTP);
getaddrinfo_demo("localhost", "sbcap", SOCK_SEQPACKET, IPPROTO_SCTP);
getaddrinfo_demo("localhost", "sbcap", SOCK_STREAM, IPPROTO_TCP);
getaddrinfo_demo("localhost", "http", SOCK_DGRAM, IPPROTO_UDPLITE);
getaddrinfo_demo("localhost", "syslog-tls", SOCK_DCCP, IPPROTO_DCCP);
Which give you:这给你:
ip: 127.0.0.1; port: 80; protocol: 132
ip: 127.0.0.1; port: 143; protocol: 6
Error -8: Servname not supported for ai_socktype
ip: 127.0.0.1; port: 29168; protocol: 132
ip: 127.0.0.1; port: 29168; protocol: 132
Error -8: Servname not supported for ai_socktype
Error -8: Servname not supported for ai_socktype
ip: 127.0.0.1; port: 6514; protocol: 33
So TCP is not the only streaming protocol, as well as UDP is not the only datagram protocol (although DCCP has its own SOCK_DCCP
and UDP-Lite doesn't have any entries in the services DB (one might argue that it doesn't need to as UDP-Lite RFC explicitly says that "UDP-Lite uses the same set of port number values assigned by the IANA for use by UDP")).所以 TCP 不是唯一的流协议,UDP 也不是唯一的数据报协议(尽管 DCCP 有自己的
SOCK_DCCP
并且 UDP-Lite 在服务 DB 中没有任何条目(有人可能会争辩说它不需要UDP-Lite RFC明确表示“UDP-Lite 使用 IANA 分配的一组相同的端口号值供 UDP 使用”))。
We don't see it often in practice these days, but if we're talking about APIs like getaddrinfo()
, they have to be designed to be somewhat future-proof, and that includes making some seemingly redundant things.这些天我们在实践中并不经常看到它,但是如果我们谈论像
getaddrinfo()
这样的 API,它们必须被设计成有点面向未来,其中包括制作一些看似多余的东西。 Only time can tell whether these things really are redundant, or not.只有时间才能证明这些东西是否真的是多余的。 In this case it's not, it's exactly the opposite.
在这种情况下,事实并非如此,恰恰相反。 If FreeBSD man page is correct, then
如果FreeBSD 手册页正确,则
The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit.
该实现首先出现在 WIDE Hydrangea IPv6 协议栈套件中。
There is still present an FAQ about this protocol stack on the Internet, from which we can guess that it was created around 1997--1998 (I'm not that old to remember such things and I don't see any other appropriate source, so correct me if I'm wrong).互联网上仍然有关于这个协议栈的常见问题解答,从中我们可以猜测它是在 1997--1998 年左右创建的(我还没有那么老记得这些事情,我没有看到任何其他合适的来源,所以如果我错了,请纠正我)。 And SCTP was defined in 2000. As I've shown with examples above, we have SCTP using this API without any problems.
SCTP 是在 2000年定义的。正如我在上面的例子中所展示的,我们使用这个 API 的 SCTP 没有任何问题。 Same story with DCCP that appeared around 2005--2006, fits into the same API perfectly.
与 2005--2006 年左右出现的 DCCP 相同的故事,完全适合相同的 API。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.