C语言连接非::1的IPv6地址失败 libssh2 SSH连接问题排查
问题根因
你定义的struct sockaddr_storage是栈上变量,未做初始化时内部会残留栈内存的随机值,映射为struct sockaddr_in6结构体后,除了你手动赋值的sin6_family、sin6_port、sin6_addr字段外,sin6_flowinfo、sin6_scope_id两个字段会是随机值:
- 本地回环地址
::1的网络栈对这两个字段的非法值容错性更高,所以可以正常连接 - 非本地IPv6地址的连接逻辑会校验这两个字段的合法性,随机值会导致连接请求无效
修复方案
在对结构体赋值前,先调用memset将整个结构体内存清零即可,修复后完整代码如下:
// 需提前引入<string.h>头文件才能使用memset #include <string.h> #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> const char *ip = "你的非本地IPv6地址"; struct sockaddr_storage storage; // 新增结构体初始化代码 memset(&storage, 0, sizeof(storage)); struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &storage; addr6->sin6_family = AF_INET6; addr6->sin6_port = htons(22); int sock; if(inet_pton(AF_INET6, ip, &addr6->sin6_addr) == 1) { if((sock = socket(AF_INET6, SOCK_STREAM, 0)) != -1) { if(connect(sock, (struct sockaddr *)(&storage), sizeof(struct sockaddr_in6)) == 0) { printf("works\n"); } close(sock); } }
补充说明:如果后续需要连接fe80开头的链路本地IPv6地址,还需要手动给
sin6_scope_id赋值对应网卡的接口序号,否则依然会连接失败。
内容的提问来源于stack exchange,提问作者weyh
相关产品推荐
相关产品推荐

