【问题标题】:Send GET Request in C to IPv6 web server on windows将 C 中的 GET 请求发送到 Windows 上的 IPv6 Web 服务器
【发布时间】:2022-01-04 03:28:06
【问题描述】:

我正在尝试向具有 IPv6 地址的网络服务器发出简单的 GET 请求,但它不起作用。我的代码必须在 Windows 上可用,所以我使用 Windows 库,例如

#include <stdio.h>
#include <winsock2.h>
#pragma comment (lib, "Ws2_32.lib")
#include <windows.h>
#include <winuser.h>
#include <string.h>

这是建立连接的代码部分:

int portno = 825;
//yes, strange port number...
const char *adress = "[2a02:842a:86d1:d001:26dd:8d7a:8202:d9a3]";
WSADATA wsa;
SOCKET sockfd;
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\n\r\n");
struct hostent *server;
struct sockaddr_in6 serv_addr;
int bytes, sent, received, total;
char response[4096];
int iResult = WSAStartup(MAKEWORD(2,2),&wsa);
sockfd = socket(AF_INET6 , SOCK_STREAM , 0 );

//while debugging i noticed that this line does not work
server = gethostbyname(adress);

memset(&serv_addr,0,sizeof(serv_addr));
printf("1\n");
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));

如果有人知道如何更改此代码以允许 IPv6 连接,请告诉我 :)

【问题讨论】:

标签: c sockets web ipv6 winsock2


【解决方案1】:

您对gethostbyname() 的调用不可能工作,因为此函数仅适用于 IPv4 地址或主机名,而您提供的是 URI 表示法 ([addr]) 的 IPv6 地址。此外,gethostbyname() 已过时,不应在新代码中使用。

由于您已经拥有 IPv6 地址,因此无需执行查找。您可以使用getaddrinfo(),但最好通过更简单的inet_pton() 将其转换为二进制形式。请记住,您需要删除封闭的 [] 括号,因为它们仅用于 URI,而不是文字地址。

这是一个例子:

const char *address = "2a02:842a:86d1:d001:26dd:8d7a:8202:d9a3";

if (inet_pton(AF_INET6, address, &serv_addr.sin6_addr.s6_addr) != 1) {
    // invalid address, handle the error somehow
}

另外,请注意正确的sockaddr_in6 具有以下字段(请参阅man 7 ipv6):

struct sockaddr_in6 {
    sa_family_t     sin6_family;   /* AF_INET6 */
    in_port_t       sin6_port;     /* port number */
    uint32_t        sin6_flowinfo; /* IPv6 flow information */
    struct in6_addr sin6_addr;     /* IPv6 address */
    uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */
};

struct in6_addr {
    unsigned char   s6_addr[16];   /* IPv6 address */
};

当您使用sin_addr、sin_family 等时,就好像它是sockaddr_in 结构一样。你想要的是:

serv_addr.sin6_family = AF_INET6;
serv_addr.sin6_port = htons(portno);

【讨论】:

  • 谢谢!经过几次搜索后,我能够在 Windows 上使用它并且它可以工作:) 但是我仍在为连接线苦苦挣扎,因为它似乎不接受 IPv6,而且我找不到任何关于如何适应的资源它到 IPv6...
  • "如果您有主机名,则可以改用 getaddrinfo()" - getaddrinfo() 支持在不执行查找的情况下解析 IP 地址文字。
  • @Bouloukaouze connect() 在AF_INET6 套接字上调用时可以很好地处理 IPv6 地址。因此,要么您的 IP 地址错误,要么您使用的 connect() 错误。至于迁移资源,见IPv6 Guide for Windows Sockets Applications
  • 谢谢,有一点我想不通:我的代码是sockfd = socket(AF_INET6 , SOCK_STREAM , 0 ); inet_pton(AF_INET6, adress, &amp;serv_addr.sin6_addr.s6_addr); memset(&amp;serv_addr,0,sizeof(serv_addr)); serv_addr.sin6_family = AF_INET6; serv_addr.sin6_port = htons(portno); if(connect(sockfd,(struct sockaddr *)&amp;serv_addr,sizeof(serv_addr)) &lt; 0) {printf("error\n");},但我收到了错误...抱歉代码我没有找到正确的表达方式跨度>
  • 你在设置IP后是认真的在做memset(&amp;serv_addr,0,sizeof(serv_addr));吗?这不可能工作:') 你在设置它之后就清除了serv_addr.sin6_addr.s6_addr。删除 memset 电话。
猜你喜欢
  • 2017-10-19
  • 2017-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多