所以,在我收到此错误后,我一直在寻找答案,几乎每个人都有一个难以解决此错误的方法,但没有人解释为什么会发生此错误,所以我不会&#39 ; t发现这个问题完全重复。
我在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));
我意识到当我提供"服务"一个数字输入,如8080,没有错误会返回,但当我使用字符串作为服务名称,如" tproxy"指向端口/ 8081,' gai_strerror'返回提到的错误。
显然,gai_strerror说:"服务名称不支持' SOCK_DGRAM'套接字类型",但为什么呢?我的意思是" getaddrinfo"不通过UDP套接字支持名称服务?
有没有其他方法可以使用UDP套接字而不是端口号来使用服务名称?如何?
答案 0 :(得分:3)
TL; DR:没有tproxy
UDP端口。
如果在服务数据库中查找UDP套接字的tproxy
服务,
getent services tproxy/udp
您没有输出,因为tproxy
不是UDP服务。如果您查看所有tproxy
服务,无论协议getent services | grep -e tproxy
如何,您都会看到
tproxy 8081/tcp
表示仅为TCP协议定义tproxy
服务。
这意味着如果您向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通信。因此,假设服务数据库应该为TCP和UDP套接字返回相同的端口号是不合理的。
换句话说,您遇到错误是因为您错误地认为由于某些服务使用TCP端口,并且在服务数据库中注册了名称,因此您应该能够使用该名称来指定UDP端口号。
TCP和UDP是单独的协议,它们的端口号空间是分开的。例如,Unix exec
r-service使用TCP端口512,而biff
邮件通知服务使用UDP端口512。
答案 1 :(得分:1)
当为service
参数提供非数字值时,会在/ etc / services文件中查找(在Linux上)。此文件将服务名称映射到端口/协议。以下是一些示例条目:
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的条目。如果你传入"域"作为服务名称,你应该得到一个结果。