hostname not translated into an IP address using W

2020-07-18 06:34发布

问题:

getaddrinfo() does not translate a hostname into an IP address and consequently does not connect() to the server. Is something wrong with my implementation - compiles with no warning messages?

Is this function call to connect correct?

connect(client, result->ai_addr, result->ai_addrlen)

Full implementation listed below:

#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <stdio.h>
#include <iostream>

#pragma comment(lib, "Ws2_32.lib")

using namespace std;

int main (
          int argc,
          char* argv[])
{
if (argc != 3)
{
    cerr << "Usage: " << argv[0] << " [hostname] [port number]\n";
    exit(EXIT_FAILURE);
}

WSADATA wsaData;
WORD wVersionRequested;
int wError;

wVersionRequested = MAKEWORD(2, 2);

wError = WSAStartup(wVersionRequested, &wsaData);

if (wError != 0)
{
    cerr << "WSAStartup failed with error: " << wError << endl;
    exit (EXIT_FAILURE);
}

/*
* Confirm that the WinSock DLL supports 2.2.
* Note that if the DLL supports versions greater
* than 2.2 in addition to 2.2, it will still return 
* 2.2 in wVersion since that is the version we 
* requested. 
*/

if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
    cerr << "Could not find a usable version of Winsock.dll." << endl;
    WSACleanup();
    exit(EXIT_FAILURE);
} else {
    cout << "The Winsock 2.2 dll was found." << endl;
}

SOCKET client;

if ((client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR)
{
    cerr << "Error: socket() return value == SOCKET_ERROR" << endl;
    WSACleanup();
    exit (EXIT_FAILURE);
}

cout << "Created a socket." << endl;

struct addrinfo *result = NULL;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

if ((wError = getaddrinfo(
                    argv[1],
                    argv[2],
                    &hints,
                    &result)) !=0 )
{
    freeaddrinfo(result);
    WSACleanup();
    if (wError == 11001)
    {
        cerr << "Error: occurred: getaddrinfo() failed "
             << wError << " - Host not found." << endl;
        exit(EXIT_FAILURE);
    }

    cerr << "Error: occurred: getaddrinfo() failed "
            << wError << endl;
    exit(EXIT_FAILURE);
}
/*
* Attempt to connect to the Server
*
*/

switch (wError = connect(client, result->ai_addr, result->ai_addrlen)) {
    case 0:
        cerr << "Resolved hostname." << endl;
        break;
    case SOCKET_ERROR:
        wError = WSAGetLastError();
        cerr << "Error: connet() failed "
                "Details: " << wError << endl;
        closesocket(client);
        freeaddrinfo(result);
        WSACleanup();
        exit(EXIT_FAILURE);
        break;
    default:
        cerr << "Fatal connect() error: unexpected "
                "return value." << endl;
        closesocket(client);
        freeaddrinfo(result);
        WSACleanup();
        exit(EXIT_FAILURE);
        break;
}

cout << "Connected to server." << endl;

closesocket(client);
freeaddrinfo(result);
WSACleanup();
exit(EXIT_SUCCESS);
}

回答1:

getaddrinfo may be giving you an IPv6 address, or perhaps the machine has more than one IP address and you're trying to connect to the wrong one.

Also, if your server is listening on 127.0.0.1 and you try to connect to the real IP address, the connection will fail. Similarly, if the server is listening on the real IP address and you try to connect using 127.0.0.1, the connection will fail. If the server listens on 0.0.0.0, both addresses should work.

To listen on 0.0.0.0, you would have code similar to this:

sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port=htons( port_num );
bind( s, (sockaddr *)&sin, sizeof( sin ) );


回答2:

Try setting the hint.ai_family to AF_UNSPEC instead of AF_INET, I believe that when AF_INET is specfied the getaddrinfo functions excepts IPv4-like address.