gpt4 book ai didi

c - Haskell:不支持的操作(协议(protocol)族不支持地址族)

转载 作者:行者123 更新时间:2023-12-02 08:21:16 25 4
gpt4 key购买 nike

我有这段代码连接到本地 Graphite (实际上只是在本地主机上运行的nc -l -p 2023):

getCarbonAddr :: Config -> IO SockAddr
getCarbonAddr cfg = do
let host = (graphiteHost . graphiteConfig) cfg
let port = (graphitePort . graphiteConfig) cfg
-- addrInfos <- getAddrInfo (Just defaultHints)
addrInfos <- getAddrInfo Nothing
(Just host)
(Just (show port))
putStrLn $ "addrInfos: " ++ show addrInfos
c <- case addrInfos of
(addrInfo : _) -> return (addrAddress addrInfo)
_ -> unsupportedAddressError host
return c
where
unsupportedAddressError h = ioError $ userError $
"unsupported address: " ++ h

主机和端口的配置值分别为“localhost”和2023。当我升级到 Yosemite 后在 OS X 上运行此程序时,我看到以下崩溃:

addrInfos: [AddrInfo {addrFlags = [], addrFamily = AF_INET6, addrSocketType = Datagram, addrProtocol = 17, addrAddress = [::1]:2023, addrCanonName = Nothing},AddrInfo {addrFlags = [], addrFamily = AF_INET6, addrSocketType = Stream, addrProtocol = 6, addrAddress = [::1]:2023, addrCanonName = Nothing},AddrInfo {addrFlags = [], addrFamily = AF_INET, addrSocketType = Datagram, addrProtocol = 17, addrAddress = 127.0.0.1:2023, addrCanonName = Nothing},AddrInfo {addrFlags = [], addrFamily = AF_INET, addrSocketType = Stream, addrProtocol = 6, addrAddress = 127.0.0.1:2023, addrCanonName = Nothing},AddrInfo {addrFlags = [], addrFamily = AF_INET6, addrSocketType = Datagram, addrProtocol = 17, addrAddress = [fe80::1%lo0]:2023, addrCanonName = Nothing},AddrInfo {addrFlags = [], addrFamily = AF_INET6, addrSocketType = Stream, addrProtocol = 6, addrAddress = [fe80::1%lo0]:2023, addrCanonName = Nothing}]
LocalJob: connect: unsupported operation (Address family not supported by protocol family)

这对我来说很奇怪,所以我决定运行这个 C 程序(在 google 上搜索“getaddrinfo”示例,更改主机名和端口,添加 ai_family 的打印):

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>

#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif

int main(void)
{
struct addrinfo *result;
struct addrinfo *res;
int error;

/* resolve the domain name into a list of addresses */
error = getaddrinfo("localhost", "2023", NULL, &result);
if (error != 0)
{
fprintf(stderr, "error in getaddrinfo: %s\n", gai_strerror(error));
return EXIT_FAILURE;
}

/* loop over all returned results and do inverse lookup */
for (res = result; res != NULL; res = res->ai_next)
{
char hostname[NI_MAXHOST] = "";

error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, NI_MAXHOST, NULL, 0, 0);
if (error != 0)
{
fprintf(stderr, "error in getnameinfo: %s\n", gai_strerror(error));
continue;
}
if (*hostname != '\0')
printf("hostname: %s. ai_family: %i\n", hostname, res->ai_family);
}

freeaddrinfo(result);
return EXIT_SUCCESS;
}

启动后,我看到了以下输出:

➜  getaddrinfotest  ./main
hostname: localhost. ai_family: 30
hostname: localhost. ai_family: 30
hostname: localhost. ai_family: 2
hostname: localhost. ai_family: 2
hostname: localhost. ai_family: 30
hostname: localhost. ai_family: 30

所以,ai_family 30 似乎是一个奇怪的东西。据我了解socket.h sources ,它就是 AF_TIPC 协议(protocol),这是一个我以前没有听说过的非常罕见的东西。我还打开了haskell的packFamily' sources并惊讶地发现它不能处理 30 的值(不知道 AF_TIPC)。

我的问题是:现在最好的做法是什么?我是否正确地理解了问题? Haskell 应该更好地处理未知的人工智能家族吗?//谢谢!

更新:我通过提示使用 ipv4 解决了问题:

addrInfos <- getAddrInfo (Just (defaultHints { addrFamily=AF_INET }))
(Just host)
(Just (show port))

但我仍然想知道如何“以正确的方式”解决这个问题。

最佳答案

默认情况下,getaddrinfo(及其 Haskell 绑定(bind) getAddrInfo)返回 addrinfo 的链接列表,其中可以包含 IPv4 地址、IPv6 地址或两者的混合。不幸的是,sockets 函数不允许将 IPv4 套接字连接到 IPv6 地址,因此当您迭代地址列表时,您需要创建正确类型的套接字:

addrinfos <- getAddrInfo Nothing (Just hostname) (Just (show port))
let first = head addrinfos
sock <- socket (addrFamily first) Stream defaultProtocol
connect sock (addrAddress first)

请注意如何将(首先是addrFamily)传递给socket函数,以便在正确的协议(protocol)族中创建套接字。

在实际代码中,您需要迭代列表 addrinfos 并尝试连接到 getAddrInfo 返回的所有地址。当您这样做时,不要忘记关闭连接失败的套接字。

关于c - Haskell:不支持的操作(协议(protocol)族不支持地址族),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26588469/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com