C - 获取地址信息 returns "Servname not supported for ai_socktype"
C - getaddrinfo returns "Servname not supported for ai_socktype"
所以,在我得到这个错误之后,我一直在这里寻找答案,几乎每个人都有一个困难的方法来修复这个错误但是没有人解释为什么会出现这个错误,所以我没有发现这个问题完全重复。
我用 C 编写了一个 TCP 套接字,我使用 "getaddrinfo" 函数使套接字与主机名一起工作,它工作得很好!你可以在 github.
上找到我的代码
但是当我试图通过 "getaddrinfo" 创建一个 UDP socket 时,我得到了这个错误:
ai_socktype
不支持服务名称
client.c
const char *host = argv[1];
const char *service = argv[2];
const char *string = argv[3];
struct addrinfo addrCriteria;
memset(&addrCriteria, 0, sizeof(addrCriteria));
addrCriteria.ai_family = AF_UNSPEC;
addrCriteria.ai_socktype = SOCK_DGRAM;
addrCriteria.ai_protocol = IPPROTO_UDP;
struct addrinfo *servAddr;
int ret = getaddrinfo(host, service, &addrCriteria, &servAddr);
if(ret != 0)
sysError(gai_strerror(ret));
我意识到当我给 "service" 一个像 8080 这样的数字输入时,不会有错误 return 但是当我使用一个字符串作为服务名称时 "tproxy" 指向 port/8081, 'gai_strerror' returns 提到的错误。
显然,gai_strerror 表示:"service names not supported for 'SOCK_DGRAM' socket types",但为什么呢?我的意思是 "getaddrinfo" 不支持通过 UDP 套接字提供名称服务的确切原因?
有没有其他方法可以使用带有 UDP 套接字的服务名称而不是端口号?怎么样?
当为 service
参数指定非数字值时,将在 /etc/services 文件中查找(在 Linux 上)。此文件将服务名称映射到 port/protocol。以下是一些示例条目:
ssh 22/tcp
telnet 23/tcp
domain 53/tcp # name-domain server
domain 53/udp
您收到错误的原因是您的 /etc/services 文件中没有 "tproxy" 的 UDP 条目。查看此文件并查找确实指定 UDP 端口的条目,例如 "domain"。那应该有 53/tcp 和 53/udp 的条目。如果您传入 "domain" 作为服务名称,您应该会返回一个结果。
TL;DR: 没有 tproxy
UDP 端口。
如果您在服务数据库中查找 tproxy
UDP 套接字服务,
getent services tproxy/udp
您没有得到任何输出,因为 tproxy
不是 UDP 服务。如果您查看所有 tproxy
服务而不考虑协议 getent services | grep -e tproxy
,您会看到
tproxy 8081/tcp
表示tproxy
服务仅为TCP协议定义。
这意味着如果您向 getaddrinfo()
请求服务 8081
的 UDP 套接字,您将找不到任何东西,因为 tproxy
只为 TCP 而不是 UDP 定义。
与您请求 xmpp-client
服务的 UDP 套接字的情况相比。至少我的服务数据库 (getent services xmpp-client/udp
) 响应
xmpp-client 5222/udp jabber-client
事实上,getaddrinfo()
很乐意为此类 UDP 套接字提供套接字描述(使用 xmpp-client
或 jabber-client
作为服务)。
因此,像 xmpp-client
这样的服务确实同时定义了 TCP 和 UDP 端口。在我的系统上,getent services | grep -e xmpp-client
显示
xmpp-client 5222/tcp jabber-client
xmpp-client 5222/udp jabber-client
因为 TCP 和 UDP 是基于 IP 的不同协议,所以服务可以使用不同的端口号进行 TCP 和 UDP 通信是有道理的。因此,假定服务数据库应该 return TCP 和 UDP 套接字的相同端口号是不合理的。
换句话说,您遇到错误是因为您错误地认为因为某些服务使用 TCP 端口,并且在服务数据库中注册了名称,您应该能够使用该名称来指定 UDP 端口号,也是。
TCP和UDP是不同的协议,它们的端口号空间是分开的。例如,Unix exec
r-服务使用 TCP 端口 512,而 biff
邮件通知服务使用 UDP 端口 512。
所以,在我得到这个错误之后,我一直在这里寻找答案,几乎每个人都有一个困难的方法来修复这个错误但是没有人解释为什么会出现这个错误,所以我没有发现这个问题完全重复。
我用 C 编写了一个 TCP 套接字,我使用 "getaddrinfo" 函数使套接字与主机名一起工作,它工作得很好!你可以在 github.
上找到我的代码但是当我试图通过 "getaddrinfo" 创建一个 UDP socket 时,我得到了这个错误:
ai_socktype
client.c
const char *host = argv[1];
const char *service = argv[2];
const char *string = argv[3];
struct addrinfo addrCriteria;
memset(&addrCriteria, 0, sizeof(addrCriteria));
addrCriteria.ai_family = AF_UNSPEC;
addrCriteria.ai_socktype = SOCK_DGRAM;
addrCriteria.ai_protocol = IPPROTO_UDP;
struct addrinfo *servAddr;
int ret = getaddrinfo(host, service, &addrCriteria, &servAddr);
if(ret != 0)
sysError(gai_strerror(ret));
我意识到当我给 "service" 一个像 8080 这样的数字输入时,不会有错误 return 但是当我使用一个字符串作为服务名称时 "tproxy" 指向 port/8081, 'gai_strerror' returns 提到的错误。
显然,gai_strerror 表示:"service names not supported for 'SOCK_DGRAM' socket types",但为什么呢?我的意思是 "getaddrinfo" 不支持通过 UDP 套接字提供名称服务的确切原因?
有没有其他方法可以使用带有 UDP 套接字的服务名称而不是端口号?怎么样?
当为 service
参数指定非数字值时,将在 /etc/services 文件中查找(在 Linux 上)。此文件将服务名称映射到 port/protocol。以下是一些示例条目:
ssh 22/tcp
telnet 23/tcp
domain 53/tcp # name-domain server
domain 53/udp
您收到错误的原因是您的 /etc/services 文件中没有 "tproxy" 的 UDP 条目。查看此文件并查找确实指定 UDP 端口的条目,例如 "domain"。那应该有 53/tcp 和 53/udp 的条目。如果您传入 "domain" 作为服务名称,您应该会返回一个结果。
TL;DR: 没有 tproxy
UDP 端口。
如果您在服务数据库中查找 tproxy
UDP 套接字服务,
getent services tproxy/udp
您没有得到任何输出,因为 tproxy
不是 UDP 服务。如果您查看所有 tproxy
服务而不考虑协议 getent services | grep -e tproxy
,您会看到
tproxy 8081/tcp
表示tproxy
服务仅为TCP协议定义。
这意味着如果您向 getaddrinfo()
请求服务 8081
的 UDP 套接字,您将找不到任何东西,因为 tproxy
只为 TCP 而不是 UDP 定义。
与您请求 xmpp-client
服务的 UDP 套接字的情况相比。至少我的服务数据库 (getent services xmpp-client/udp
) 响应
xmpp-client 5222/udp jabber-client
事实上,getaddrinfo()
很乐意为此类 UDP 套接字提供套接字描述(使用 xmpp-client
或 jabber-client
作为服务)。
因此,像 xmpp-client
这样的服务确实同时定义了 TCP 和 UDP 端口。在我的系统上,getent services | grep -e xmpp-client
显示
xmpp-client 5222/tcp jabber-client
xmpp-client 5222/udp jabber-client
因为 TCP 和 UDP 是基于 IP 的不同协议,所以服务可以使用不同的端口号进行 TCP 和 UDP 通信是有道理的。因此,假定服务数据库应该 return TCP 和 UDP 套接字的相同端口号是不合理的。
换句话说,您遇到错误是因为您错误地认为因为某些服务使用 TCP 端口,并且在服务数据库中注册了名称,您应该能够使用该名称来指定 UDP 端口号,也是。
TCP和UDP是不同的协议,它们的端口号空间是分开的。例如,Unix exec
r-服务使用 TCP 端口 512,而 biff
邮件通知服务使用 UDP 端口 512。