views:

921

answers:

2
  • Question:

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

EDIT:

  • 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  A: 

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.

arul
OK: if hostname is "SAMPLE", if passed as an argument - doesn't work but as an IP address (on local machine) it works: such as 127.0.0.1
Aaron
Strange... not sure why
Aaron
Are you sure that the provided hostname is valid ?
arul
From the cmd-line: hostname returns SAMPLEso: SAMPLE 1234 (where the server is running) returns:Error: connet() failed Details: 10061
Aaron
Ok, is the port you provided correct ? Error 10061 means 'connection refused' which usually is a sign of wrongly chosen port.
arul
Yes confirmed: TCP, Local port 1234, local address 127.0.0.1 - but not sure why: 127.0.0.1 1234 - works but not: SAMPLE 127.0.0.1 - as SAMPLE is hostname?
Aaron
It maybe a typo but: with SAMPLE 127.0.0.1 the app is trying to connect to a SAMPLE host on port 127.0.0.1 - which is invalid.
arul
Actually: SAMPLE is == 192.168.1.64. But 127.0.0.1 works
Aaron
Thanks for your assistance arul +1
Aaron
+1  A: 

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 ) );
Graeme Perrow
How to set the server to listen on 0.0.0.0?
Aaron
This is my first Socket implementation on Windows :( I have much to learn :)
Aaron
You pass the address to listen on into the bind() call before calling listen. You can use INADDR_ANY as a shortcut.
Graeme Perrow
Updated the answer to include this.
Graeme Perrow
Thanks Graeme - Wish I could vote like 20 times!!!! :D I'm a happy student :D
Aaron