Winsock 数据不是从 IP 检索的,而是从普通 URL 检索的

Winsock data is not retrieved from an IP, but it's retrieved from a normal URL

本文关键字:检索 URL IP Winsock 数据      更新时间:2023-10-16

我有一个用Winsock获取网页内容的函数,我遇到的问题是,我在指定URL时收到页面,而在用IP 替换它时却什么都得不到

这是有效的:get_Website("www.google.com"(;

这不是:get_Website("100.111.33.77"(;

// Function
void get_Website(string url ){
WSADATA wsaData;
SOCKET Socket;
SOCKADDR_IN SockAddr;
int lineCount=0;
int rowCount=0;
struct hostent *host;
string get_http;

get_http = "POST / HTTP/1.1rnHost: " + url + "rnConnection: closernrn";

if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0){
cout << "WSAStartup failed.n";
system("pause");
//return 1;
}
Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
host = gethostbyname(url.c_str());
SockAddr.sin_port=htons(80);
SockAddr.sin_family=AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0){
cout << "Could not connect";
system("pause");
//return 1;
}
send(Socket,get_http.c_str(), strlen(get_http.c_str()),0 );
int nDataLength;
while ((nDataLength = recv(Socket,buffer,10000,0)) > 0){
int i = 0;
while (buffer[i] >= 32 || buffer[i] == 'n' || buffer[i] == 'r'){
website_HTML+=buffer[i];
i += 1;
}
}
closesocket(Socket);
WSACleanup();
}

IP地址不是主机名,因此不要使用gethostbyname()来解析IP地址。首先检查输入是否为IP,如果不是,则将其解析为主机名。在您的示例中,由于您使用的是AF_INET,因此可以简单地使用inet_addr()进行检查,例如:

SockAddr.sin_addr.s_addr = inet_addr(url.c_str());
if (Sockaddr.sin_addr.s_addr == INADDR_NONE)
{
host = gethostbyname(url.c_str());
if (!host) {
// could not resolve...
return;
}
if (host->h_addrtype != AF_INET) {
// did not resolve to IPv4...
return;
}
Sockaddr.sin_addr.s_addr = *reinterpret_cast<u_long*>(host->h_addr); 
}

请注意,一个主机名可以解析为多个IP地址,因此您应该遍历整个host->h_addr_list,尝试将connect()循环到每个IP,直到其中一个成功为止。

不过,您确实应该使用getaddrinfo(),因为gethostbyname()已被弃用,例如:

addrinfo hints = {};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
addrinfo *result = NULL;
if (getaddrinfo(url.c_str(), "80", &hints, &result) != 0) {
// could not resolve...
return;
}
bool connected = false;
for(addrinfo *addr = result; (addr != NULL) && (!connected); addr = addr->ai_next) {
connected = (connect(Socket, addr->ai_addr, addr->ai_addrlen) == 0);
}
freeaddrinfo(result);
if (!connected) {
// could not connect...
return;
}