Windows环境下使用C语言向IPv6 Web服务器发送GET请求的问题咨询
问题原因
gethostbyname是仅支持IPv4的废弃API,无法解析IPv6地址,且不能识别带方括号包裹的IPv6地址格式- 地址结构参数配置错误:你声明了IPv6专用的
sockaddr_in6结构体,但后续赋值时用了IPv4的AF_INET协议族、sin_addr等字段,和IPv6不匹配 - 传入
gethostbyname的IPv6地址带方括号,该格式仅用于HTTP Host头,原生地址解析不识别方括号
修复方案
1. 替换地址解析API
使用支持IPv6的getaddrinfo API替代废弃的gethostbyname,可以自动适配IPv4/IPv6地址解析,不需要手动处理地址结构差异。
2. 修正地址结构配置
全程使用IPv6对应的参数配置地址结构体,或者直接用getaddrinfo返回的地址参数传参给connect,避免手动赋值出错。
3. 地址格式调整
用于解析的原始IPv6地址去掉外层方括号,仅保留Host头里的带方括号格式即可。
修正后的完整代码片段
#include <stdio.h> #include <winsock2.h> #include <ws2tcpip.h> // 新增getaddrinfo所需头文件 #pragma comment (lib, "Ws2_32.lib") #include <windows.h> #include <string.h> int main() { int portno = 825; // 解析用的IPv6地址去掉方括号,Host头里保留带方括号的格式即可 const char *address_raw = "2a02:842a:86d1:d001:26dd:8d7a:8202:d9a3"; const char *port_str = "825"; WSADATA wsa; SOCKET sockfd = INVALID_SOCKET; char message[4096] = "GET //page//index.php?data=somedata HTTP/1.1\r\nHost: [2a02:842a:86d1:d001:26dd:8d7a:8202:d9a3]\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\nConnection: close\r\n\r\n"; struct addrinfo hints = {0}, *result = NULL, *ptr = NULL; int bytes, sent, received, total; char response[4096]; int iResult; // 初始化Winsock iResult = WSAStartup(MAKEWORD(2,2),&wsa); if (iResult != 0) { printf("WSAStartup失败: %d\n", iResult); return 1; } // 配置getaddrinfo参数,指定IPv6协议 hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; // 解析IPv6地址 iResult = getaddrinfo(address_raw, port_str, &hints, &result); if (iResult != 0) { printf("getaddrinfo失败: %d\n", iResult); WSACleanup(); return 1; } // 遍历返回的地址列表创建socket并连接 for(ptr = result; ptr != NULL; ptr = ptr->ai_next) { sockfd = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (sockfd == INVALID_SOCKET) { printf("socket创建失败: %ld\n", WSAGetLastError()); continue; } iResult = connect(sockfd, ptr->ai_addr, (int)ptr->ai_addrlen); if (iResult == SOCKET_ERROR) { closesocket(sockfd); sockfd = INVALID_SOCKET; continue; } break; } freeaddrinfo(result); if (sockfd == INVALID_SOCKET) { printf("连接服务器失败\n"); WSACleanup(); return 1; } // 发送请求 sent = send(sockfd, message, strlen(message), 0); if (sent == SOCKET_ERROR) { printf("发送失败: %d\n", WSAGetLastError()); closesocket(sockfd); WSACleanup(); return 1; } // 接收响应示例 do { received = recv(sockfd, response, sizeof(response)-1, 0); if (received > 0) { response[received] = '\0'; printf("%s", response); } else if (received == 0) { printf("\n连接关闭\n"); } else { printf("接收失败: %d\n", WSAGetLastError()); } } while (received > 0); // 清理资源 closesocket(sockfd); WSACleanup(); return 0; }
内容的提问来源于stack exchange,提问作者Bouloukaouze
相关产品推荐
相关产品推荐

