我正在写一个UDP套接字程序,它从命令行提供了一个地址。
为了使发送和写入更容易,我使用getaddrinfo将地址转换为sockaddr结构:sockaddr_in或sockaddr_in6。现在我明白我应该使用sockaddrs的联合:
typedef union address
{
struct sockaddr s;
struct sockaddr_in s4;
struct sockaddr_in6 s6;
struct sockaddr_storage ss;
} address_t;
据我所知,他们不能成为指针,以避免隐藏严格的别名问题。我无法将来自getaddrinfo的addrinfo的信息无缝地放入此address_t:
struct addrinfo hint, *serv = NULL;
address_t addr;
hint.ai_family = AF_UNSPEC;
hint.ai_flags = 0;
hint.ai_socktype = SOCK_DGRAM;
hint.ai_protocol = IPPROTO_UDP;
ret = getaddrinfo(address_sr.c_str(), s_port.c_str(), &hint, &serv);
//address_sr and s_port are strings with the address and port
switch (serv->ai_addr) {
case AF_INET: {
addr->s4 = * (sockaddr_in*) serv->ai_addr;
//Here I want to fill the address_t struct with information
//This line causes a segfault
}
break;
case AF_INET6: {
addr->s6 = * (sockaddr_in6*) serv->ai_addr;
//Conversion here
}
break;
另外,复制内存:
memcpy(&addr, serv->ai_addr, serv->ai_addrlen);
也导致段错误。
我该怎么做?我尝试了十几种不同的方法,但我无法弄明白。如何将addrinfo的地址添加到此联合中?我使用sockaddr_storage还是sockaddr_ins?
编辑:编辑以获得清晰度和其他代码信息。
答案 0 :(得分:1)
您需要取消引用指针。
addr->s4 = *(sockaddr_in*) serv->ai_addr;
答案 1 :(得分:1)
我认为你没有getaddrinfo正确。
关于第三个论点:
const struct addrinfo *hints
hints参数指向指定的addrinfo结构 选择返回的套接字地址结构的标准 res指出的列表。如果提示不为NULL,则指向addrinfo ai_family,ai_socktype和ai_protocol指定的结构 限制返回的套接字地址集的条件 的getaddrinfo()[...]
例如,您可以仅询问IPv4地址系列,和/或仅询问数据报套接字(考虑到您尝试使用UDP,这可能没问题)。 基本上,你提供了一个addrinfo实例,设置了感兴趣的字段,然后将指向它的指针传递给函数,作为它的第三个参数:
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
ret = getaddrinfo(address_sr.c_str(), s_port.c_str(), &hint, &serv);
在这个例子中,函数不仅可以返回一个,而且可以返回整个地址结构列表:
getaddrinfo()函数分配并初始化链表 addrinfo结构,每个网络地址与节点匹配一个 和服务,受提示和退货限制 指向res中列表开头的指针。链接中的项目 列表由ai_next字段链接。
所以你必须以这种方式遍历函数结果:
for (rp = serv; rp != NULL; rp = rp->ai_next)
我强烈建议您仔细阅读我提供的链接中的文档。还有一个长而详细的例子可以单独解决你的问题。
答案 2 :(得分:0)
sockaddr_storage
足以容纳任何 sockaddr_...
类型,从而使address_t
同样大。所以,我只需memcpy()
一次操作serv->ai_addr
并摆脱switch
,例如:
struct addrinfo hints = {};
struct addrinfo *addrs, *serv;
address_t addr;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
...
ret = getaddrinfo(address_sr.c_str(), s_port.c_str(), &hint, &addrs);
if (ret == 0)
{
for (serv = addrs; serv != NULL; serv = serv->ai_next)
{
memcpy(&addr, serv->ai_addr, serv->ai_addrlen);
...
}
freeaddrinfo(addrs);
}