网络编程之基本函数一
hostent *gethostbyname(const char *name);
这个函数的传入值是域名或者主机名,例如"www.google.cn"等等。传出值,是一个hostent的结构。如果函数调用失败,将返回NULL。
struct hostent { char *h_name; char **h_aliases; int h_addrtype; int h_length; char **h_addr_list; #define h_addr h_addr_list[0] };
hostent->h_name
表示的是主机的规范名。例如www.google.com的规范名其实是www.l.google.com。
hostent->h_aliases
表示的是主机的别名.www.google.com就是google他自己的别名。有的时候,有的主机可能有好几个别名,这些,其实都是为了易于用户记忆而为自己的网站多取的名字。
hostent->h_addrtype
表示的是主机ip地址的类型,到底是ipv4(AF_INET),还是pv6(AF_INET6)
hostent->h_length
表示的是主机ip地址的长度
hostent->h_addr_list
表示的是主机的ip地址,注意,这个是以网络字节序存储的。不能直接用printf带%s参数来打印,所以到真正需要打印出这个IP的话,需要调用inet_ntop()。
linux 下可以调用const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) :
这个函数,是将类型为af的网络地址结构src,转换成主机序的字符串形式,存放在长度为cnt的字符串中。返回指向dst的一个指针。如果函数调用错误,返回值是NULL。
以下是简单的例子:
因为windows中没有inet_ntop函数可以使用,所以必须重写这个函数,幸亏有人已经做过这样的事情。
// PrintAddress.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <Windows.h> #include <WinSock.h> #include <iostream> using namespace std; #pragma comment(lib,"ws2_32.lib") #define IN6ADDRSZ 128 #define INT16SZ 16 #define INET6_ADDRSTRLEN 128 #ifdef _WIN32 typedef struct _BASE { long base; long len; }BASE; static const char* inet_ntop4(const u_char* src, char* dst, size_t size) { static const char fmt[] = "%u.%u.%u.%u"; char tmp[sizeof("255.255.255.255")]; int l = sprintf_s(tmp,"%d.%d.%d.%d", src[0], src[1], src[2], src[3]); if(l <= 0 ||l >size) { return NULL; } strcpy_s(dst, size, tmp); return dst; } static const char* inet_ntop6(const u_char* src, char* dst, size_t size) { /* Note that int32_t and int16_t need only be "at least" large enough * to contain a value of the specified size. On some systems, like * Crays, there is no such thing as an integer variable with 16 bits. * Keep this in mind if you think this function should have been coded * to use pointer overlays. All the world's not a VAX. */ char tmp [INET6_ADDRSTRLEN+1]; char *tp; BASE best, cur; u_long words [IN6ADDRSZ / INT16SZ]; int i; /* Preprocess: * Copy the input (bytewise) array into a wordwise array. * Find the longest run of 0x00's in src[] for :: shorthanding. */ memset (words, 0, sizeof(words)); for (i = 0; i < IN6ADDRSZ; i++) { words[i/2] |= (src[i] << ((1 - (i % 2)) << 3)); } best.base = -1; cur.base = -1; for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { if (words[i] == 0) { if (cur.base == -1) { cur.base = i, cur.len = 1; } else cur.len++; } else if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) { best = cur; } cur.base = -1; } } if ((cur.base != -1) && (best.base == -1 || cur.len > best.len)) { best = cur; } if (best.base != -1 && best.len < 2) { best.base = -1; } /* Format the result. */ tp = tmp; for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { /* Are we inside the best run of 0x00's? */ if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { if (i == best.base) { *tp++ = ':'; } continue; } /* Are we following an initial run of 0x00s or any real hex? */ if (i != 0) { *tp++ = ':'; } /* Is this address an encapsulated IPv4?*/ if (i == 6 && best.base == 0 &&(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { tp += strlen(tp); break; } tp += sprintf (tp, "%lX", words[i]); } /* Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) { *tp++ = ':'; } *tp++ = '\0'; /* Check for overflow, copy, and we're done. */ if ((size_t)(tp - tmp) > size) { return NULL; } strcpy_s(dst, size, tmp); return dst; } const char* inet_ntop(int af, void *src, char *dst, size_t size) { switch (af) { case AF_INET : return inet_ntop4 ((u_char*)src, dst, size); #ifdef INET6 case AF_INET6: return inet_ntop6 ((const u_char*)src, dst, size); #endif default : return NULL; } } int _tmain(int argc, _TCHAR* argv[]) { char str[32]; char* ip = "www.baidu.com"; WSAData wsaData; if(WSAStartup(0x22, &wsaData) != 0) { return 0; } LPHOSTENT host = gethostbyname(ip); if(host != NULL) { cout<<host->h_name<<endl; cout<<host->h_length<<endl; for(char** ptr = host->h_aliases; *ptr != NULL; ptr++) { cout<<"Alias:"<<*ptr<<endl; } for(char** ptr = host->h_addr_list; *ptr != NULL; ptr++) { cout<<"Address:"<<inet_ntop(AF_INET,ptr, str, sizeof(str))<<endl; } cout<<"First address:"<<inet_ntop(AF_INET, host->h_addr, str, sizeof(str))<<endl; } system("pause"); return 0; } #endif
输出结果为: