gethostbyname

I have code here that is designed to do exactly what I want:

it prompts the user to enter a domain name, then uses gethostbyname, or gethostbyaddr to resolve what the user puts in.

However, I can't run it in Windows based Visual Studio 2010.
There's a red, squiggly line under things such as printf, iResult, and host_name that give the following error:

ERROR: This declaration has no storage class or type specifier

I think it's a winsock 1 vs. 2 declaration problem, but not sure.


Code:


//----------------------
// Declare and initialize variables
hostent* remoteHost;
char* host_name;
unsigned int addr;

//----------------------
// User inputs name of host
printf("Input name of host: ");

//----------------------
// Allocate 64 byte char string for host name
host_name = (char*) malloc(sizeof(char)*64);
fgets(host_name, 64, stdin);

// If the user input is an alpha name for the host, use gethostbyname()
// If not, get host by addr (assume IPv4)
if (isalpha(host_name[0])) { /* host address is a name */
// if hostname terminated with newline '\n', remove and zero-terminate
if (host_name[strlen(host_name)-1] == '\n')
host_name[strlen(host_name)-1] = '\0';
remoteHost = gethostbyname(host_name);
}
else {
addr = inet_addr(host_name);
remoteHost = gethostbyaddr((char *)&addr, 4, AF_INET);
}

if (WSAGetLastError() != 0) {
if (WSAGetLastError() == 11001)
printf("Host not found...\nExiting.\n");
}
else
printf("error#:%ld\n", WSAGetLastError());

// The remoteHost structure can now be used to
where is it that you're initializing WSA?
is that your full code?
You must call WSAStartup before you use winsock functions, otherwise the use of the windsock dll isn't initalized and you'll probably get a whole bunch of errors.

Also, are you including Winsock2.h?
Are you linking ws2_32.lib properly?

also, please use code tags when posting code. (can be found to the right: the <> button.)
That's the question. I'm pretty sure that I have to initialize Winsock 2 and added the code to do so, but it didn't work.

I know I have to link to the directory and the ws2_32.lib and thought I did it properly.

Can you help with the code for initializing winsock 2?

I've attached the new code and added #includes that I "thought" would help. I KNOW that I have to initialize the winsock2 as well.
See in the code below (properly between the <> tags - thanks for that)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Declare and initialize variables
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")

int main(int argc, char **argv)
hostent* remoteHost;
char* host_name;
unsigned int addr;

//----------------------
// User inputs name of host
printf("Input name of host: ");

//----------------------
// Allocate 64 byte char string for host name
host_name = (char*) malloc(sizeof(char)*64);
fgets(host_name, 64, stdin);

// If the user input is an alpha name for the host, use gethostbyname()
// If not, get host by addr (assume IPv4)
if (isalpha(host_name[0])) {   /* host address is a name */
  // if hostname terminated with newline '\n', remove and zero-terminate 
  if (host_name[strlen(host_name)-1] == '\n') 
    host_name[strlen(host_name)-1] = '\0';
  remoteHost = gethostbyname(host_name);
}
else  { 
  addr = inet_addr(host_name);
  remoteHost = gethostbyaddr((char *)&addr, 4, AF_INET);
}

if (WSAGetLastError() != 0) {
  if (WSAGetLastError() == 11001)
  printf("Host not found...\nExiting.\n");
}
else
  printf("error#:%ld\n", WSAGetLastError());

// The remoteHost structure can now be used to
// access information about the host 
Oh, you haven't got brackets around the main function body
1
2
3
4
5
6
7
8
9
int main(int argc, char **argv)
{ //<---- IMPORTANT
    hostent *remoteHost;

//...... ...... //

    else
        printf("error#:%1d\n", WSAGetLastError());
} //<--- IMPORTANT 


http://www.cplusplus.com/forum/beginner/86649/
My reply to that thread details how to initialize winsock. Although, if you're just using gethostbyname you might not run into any errors. However, you should always initialize it anyway.

EDIT: (spelling)
Last edited on
Thanks a ton, Thumper.

The program works now.
It prompts me for a domain, for which I enter "www.google.com" as an example, but it delivers back an error#:0

Not sure what that is, but I'll have a look.
Thanks again.
You need to initialise the Network stack on Windows (with WsaStartup)
Okay.
I think I've initialized the stack with WsaStartup under the "//INITIALIZE WINSOCK 2" comment, but I could be wrong. Have a look. Again, it works through the code and actually prompts me for a host name. I'm allowed to enter the hostname, but it delivers back the error,

error#:0

Obviously, we're looking for it to resolve the hostname to an ip address, or vice-versa.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// Declare and initialize variables
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")
#include <iostream>

int main(int argc, char **argv)
{
	hostent* remoteHost;
		char* host_name;	
		unsigned int addr;

		//Initialize WINSOCK 2
		WSADATA wsaData; //structure that holds information about current wsock version.
		if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0) //start wsock version 2.2. Function returns
		//0 if successful, otherwise, there was an error that needs to be reported.
		{
		std::cout << "WSAStartup failed: " << WSAGetLastError(); //report the error if there is one
		return 1; //exit the program. 
		}
//-------------------------------------------------------------------------------------------------		
		// User inputs name of host
		printf("Input name of host: ");
//-------------------------------------------------------------------------------------------------
		// Allocate 64 byte char string for host name
		host_name = (char*) malloc(sizeof(char)*64);
		fgets(host_name, 64, stdin);
//-------------------------------------------------------------------------------------------------
		// If the user input is an alpha name for the host, use gethostbyname()
		// If not, get host by addr (assume IPv4)
		if (isalpha(host_name[0])) {   /* host address is a name */
		// if hostname terminated with newline '\n', remove and zero-terminate 
			if (host_name[strlen(host_name)-1] == '\n') 
			host_name[strlen(host_name)-1] = '\0';
			remoteHost = gethostbyname(host_name);
			}
			else  { 
			addr = inet_addr(host_name);
			remoteHost = gethostbyaddr((char *)&addr, 4, AF_INET);
			}

			if (WSAGetLastError() != 0) {
				if (WSAGetLastError() == 11001)
				printf("Host not found...\nExiting.\n");
			}
			else
			printf("error#:%ld\n", WSAGetLastError());

}
I might be mistaken, but I believe WSAGetLastError() is not guaranteed to return 0 if there is no error. It stores the previous error that has occurred in the thread indefinitely, and may or may not return the value 0 if no error has occured at all.
That said, the following would be an invalid assumption
1
2
3
if(WSAGetLastError() != 0) { //I assume this is to see if there has been an error
//...
}


A better way to check for errors is to use the return codes for individual winsock functions, such as what you did with line 17, checking to see if WSAStartup had an error. WSAStartup() guarantees that it will return a nonzero value if there has been an error. In which case, we call WSAGetLastError() and return.

For example, gethostbyname() returns a NULL pointer if there was an error. So check to see if an error has occurred on that function call:
1
2
3
4
if((remoteHost = gethostbyname(host_name) == NULL) {
    cout << "gethosbyname failed: " << WSAGetLastERror() << endl;
    return 1;
}


Doing this will narrow down what is throwing an error (if an actual error is being thrown at all).

EDIT:
Also, of course your code would show that there has been an error #0.
If, in fact, WSAGetLastError() returns zero, your if statement checks whether it does not equal zero. That means the else section of the code will be executed because WSAGetLastError equals 0. And then the else body prints out that 0.

Point being, there is probably no error occurring.
Last edited on
So putting in the following makes it work:
1
2
3
4
5
6
7
8
9
10
	if (WSAGetLastError() != 0) {
		if (WSAGetLastError() == 11001)
			printf("Host not found...\nExiting.\n");
		 else 
			printf("error#:%ld\n", WSAGetLastError());
		
		return (2);
	}

	printf("Remote host name: %s\n", remoteHost->h_name);


However, it only echoes what you put in.
How do I get it to spit out an ip address?
Have you read the documentation for the hostent structure at all..?
hostent::h_name is spitting out the name of the website because that's what it is. If you want the IP addresses, you need to use the member of hostent called h_addr_list. You can read the docs here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms738552(v=vs.85).aspx
msdn is a really good reference for these things.

So h_addr_list is "A NULL-terminated list of addresses for the host," which means we can loop through it because we know the last entry will be NULL.
Each member of h_addr_list is a char array, which contains a meaningless glob of information unless we cast it to an in_addr structure structure (microsofts structure that represents an ipv4 address: http://msdn.microsoft.com/en-us/library/windows/desktop/ms738571(v=vs.85).aspx)
After we cast it to an in_addr, it can be output with the function inet_ntoa, which formats an in_addr structure to a char array representing the IP.
1
2
3
4
5
for(int i = 0; remoteHost->h_addr_list[i] != NULL; ++i) //loop until h_addr_list[i] is null
{
     in_addr *address = reinterpret_cast<in_addr*>(h_addr_list[i]); //cast to an in_addr pointer
     printf("Remote host name: %s\n", inet_ntoa(*addr)); //output IP with inet_ntoa
}


Most of this is available in the winsock documentation. You should start making pretty good friends with msdn if you expect to continue dealing with Windows APIs.

EDIT: Also, I detailed this pretty well in the post I linked you to earlier.. http://www.cplusplus.com/forum/beginner/86649/
Last edited on
Topic archived. No new replies allowed.