C - getaddrinfo返回" ai_socktype"

时间:2017-07-13 18:37:17

标签: c sockets udp getaddrinfo

所以,在我收到此错误后,我一直在寻找答案,几乎每个人都有一个难以解决此错误的方法,但没有人解释为什么会发生此错误,所以我不会&#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套接字而不是端口号来使用服务名称?如何?

2 个答案:

答案 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-clientjabber-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的条目。如果你传入"域"作为服务名称,你应该得到一个结果。