1 说明
gethostbyname是由主机名得到一个hostent结构体指针。
gethostbyaddr是根据给定IP地址、地址长度、地址类型得到一个hostent结构体指针。
该hostent结构体包括:主机名、主机别名s,地址类型、地址长度、IP地址s。
2 函数和数据结构
①gethostbyname
struct hostent FAR* gethostbyname(
const char FAR* name //主机名
);
主机名可由gethostname取得。
eg.
char name[50];
memset(name, '\0', sizesof(name));
gethostname(name);
PHONSTENT pHost = NULL;
pHost = gethostbyname(name);
②gethostbyaddr
struct hostent FAR* gethostbyaddr(
const char FAR* addr, // [in] 网络字节序IP地址
int len, // [in] 地址长度,AF_INET类型中该长度为4
int type // [in] 地址类型,一般为AF_INET(IPv4),另有AF_INET6(IPv6),AF_UNIX等等
);
函数说明:值得注意的是第一个参数,必须是网络字节序的地址,在实际使用过程中发现这个参数最容易出错。
使用时通过实验得知:该参数可以通过struct in_addr来赋予(sizeof(struct in_addr) == 4),也可以通过把点分十进制IP地址通过inet_addr转换成网络字节序地址赋给u_long类型变量,再取地址转换为const char* 类型赋予, 详见例子。
eg.
★//通过struct in_addr结构体赋予
struct in_addr addr;
const char* ip = "192.168.0.110";
addr.S_un.S_addr = inet_addr(ip);
PHOSTENT pHost = NULL;
pHost = gethostbyaddr((const char*)&in_addr, 4, AF_INET);
★//通过inet_addr函数把IP地址转换为网络字节序地址
unsigned long ipAddr;
char* ip = "192.168.0.110";
ipAddr = inet_addr(ip); //得到网络字节序地址
pHost = gethostbyaddr((const char*)&ipAddr, 4, AF_INET);
说明:上面这两种写法实在有点蛋疼,因为其实都是一个意思,addr结构体的S_un.S_addr成员也是u_long类型,这样实在多余! 但是,请注意还有但是! 这正是我在写代码的过程中迷糊的地方,编译器一直在这里报错,不是报不能把char* 转换为const char* 就是得到的主机信息不准确,在写这篇笔记的时候又改了改代码,改成第二种写法也可以正确得到结果,于是知道这两种写法是一样的,记住!!!
③struct hostent
typedef struct hostent{
char FAR* h_name; //主机名
char FAR* FAR* h_aliases; //主机别名s
short h_addrtype; //地址类型
short h_length; //地址长度,单位字节,IPv4为32位4字节
char FAR* FAR* h_addr_list; //IP地址s(列表)
}HOSTENT, *PHOSTENT;
实例
①界面
②代码
/76GetHostByXXXDlg.h 类声明///
#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")
// Generated message map functions
//{{AFX_MSG(CMy76GetHostByXXXDlg)
//codes
afx_msg void OnBtnGethostname(); //左侧“获得主机名”按钮函数
afx_msg void OnBtnGetinfo(); //左侧“获得主机信息”按钮函数
afx_msg void OnBtnGetinfo2(); //右侧“获得主机信息”按钮函数
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
/76GetHostByXXXDlg.cpp 类定义///
//对话框初始化时,初始化socekt
BOOL CMy76GetHostByXXXDlg::OnInitDialog()
{
//codes
WSADATA wsaData;
if(0 != WSAStartup(MAKEWORD(2, 0), &wsaData))
{
MessageBox("startup error!");
return FALSE;
}
//codes
}
//左侧“获得主机名”按钮函数
void CMy76GetHostByXXXDlg::OnBtnGethostname()
{
// TODO: Add your control notification handler code here
char localName[100];
memset(localName, '\0', sizeof(localName));
if(0 != gethostname(localName, sizeof(localName)))
{
CString strError = _T("错误代码:");
CString strTemp;
strTemp.Format("%d", WSAGetLastError());
strError += strTemp;
MessageBox(strError, _T("提示"), MB_OKCANCEL);
return;
}
SetDlgItemText(IDC_EDIT_HOSTNAME, localName);
}
//左侧“获得主机信息”按钮函数
void CMy76GetHostByXXXDlg::OnBtnGetinfo()
{
//从控件获取主机名,如果为空则默认本机
PHOSTENT pHost = NULL;
CString strTemp = "";
GetDlgItemText(IDC_EDIT_HOSTNAME, strTemp);
CString strHost = _T("主机名:");
strHost += "\r\n" + strTemp;
//获取HOSTENT结构体
pHost = gethostbyname(strTemp);
if (NULL == pHost)
{
CString strError = _T("错误代码:");
strTemp.Format("%d", WSAGetLastError());
strError += strTemp;
MessageBox(strError, _T("提示"), MB_OKCANCEL);
return;
}
//获取主机别名s
char** pAliases = NULL;
pAliases = pHost->h_aliases;
CPtrArray ptrArrar;
for (; *pAliases != NULL; pAliases ++)
{
ptrArrar.Add(*pAliases);
}
CString strHostName = _T("主机别名列表:");
int i = ptrArrar.GetSize();
//如果主机没有别名
if (i < 1)
{
strHostName += _T("无");
}
else
{
for (int j = 0; j < i; j ++)
{
strHostName += "\r\n";
strHostName += (char*)ptrArrar.GetAt(j);
}
}
//获取地址类型
short addrType = pHost->h_addrtype;
if(2 == addrType)
{
strTemp = "AF_INET";
}
else if (23 == addrType)
{
strTemp = "AF_INET6";
}
else if (1 == addrType)
{
strTemp == "AF_UNIX";
}
else
{
strTemp.Format("%d", addrType);
}
CString strAddr = _T("地址类型:" )+ strTemp;
//获取地址长度
short addrLength = pHost->h_length;
strTemp.Format("%d", addrLength);
CString strAddrLength = _T("地址长度:") + strTemp;
//获取IP地址列表
char** pIP = NULL;
pIP = pHost->h_addr_list;
char* IP = NULL;
CPtrArray ptrArrarIP;
for (; *pIP != NULL; pIP ++)
{
IP = inet_ntoa(*(struct in_addr *)*pIP);
ptrArrarIP.Add(IP);
}
CString strIP = _T("IP地址列表:");
int m = ptrArrarIP.GetSize();
for (int n = 0; n < m; n ++)
{
strIP += "\r\n";
strIP += (char*)ptrArrarIP.GetAt(n);
}
CString str = _T("主机信息如下:");
str += "\r\n\r\n";
str += strHost/*主机名*/ + "\r\n\r\n" + strHostName/*主机别名*/ + "\r\n\r\n" + strAddr/*地址类型*/ + "\r\n\r\n"\
+ strAddrLength/*地址长度*/ + "\r\n\r\n" + strIP/*IP地址列表*/ + "\r\n";
//给显示信息控件赋值
SetDlgItemText(IDC_EDIT_HOSTINFO, str);
//删除集合元素
ptrArrar.RemoveAll();
ptrArrarIP.RemoveAll();
}
//右侧“获得主机信息”按钮函数
void CMy76GetHostByXXXDlg::OnBtnGetinfo2()
{
// TODO: Add your control notification handler code here
BYTE field0 = 0;
BYTE field1 = 0;
BYTE field2 = 0;
BYTE field3 = 0;
//IP地址正确性检查
if( (((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(field0, field1, field2, field3)) < 4 )
{
MessageBox(_T("请填入正确的IP地址!"), _T("提示"), MB_OKCANCEL);
((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->SetFocus();
return;
}
CString strIP = ""; //用来保存点分十进制IP地址
CString temp = "";
temp.Format("%d", field0);
strIP = temp + ".";
temp.Format("%d", field1);
strIP += temp + ".";
temp.Format("%d", field2);
strIP += temp + ".";
temp.Format("%d", field3);
strIP += temp; //点分十进制IP地址取得
PHOSTENT pHost = NULL;
CString strTemp = "";
//有点蛋疼的写法
IN_ADDR ipaddr;
ipaddr.S_un.S_addr = inet_addr((LPCTSTR)(strIP));
pHost = gethostbyaddr((const char*)&ipaddr, 4, AF_INET);
//不蛋疼的写法
//const char* ipp = "192.168.0.110";
//unsigned long aa = inet_addr(ipp);
//pHost = gethostbyaddr((const char*)&aa, 4, AF_INET);
if (NULL == pHost)
{
CString strError = _T("错误信息:");
strTemp.Format("%d", WSAGetLastError());
strError += strTemp;
MessageBox(strError, _T("提示"), MB_OKCANCEL);
return;
}
//取得主机名
CString strHost = _T("主机名:");
strHost += "\r\n";
strHost += pHost->h_name;
//取得主机别名
CStringArray strArray;
CString strHostName = _T("主机别名:");
char** pAliases = NULL;
pAliases = pHost->h_aliases;
for (; *pAliases != NULL; pAliases ++)
{
strArray.Add(*pAliases);
}
//如果没有主机别名
int count = strArray.GetSize();
if (count < 1)
{
strHostName += _T("无");
}
else
{
for (int i = 0; i < count; i ++)
{
strHostName += strArray.GetAt(i) + "\r\n";
}
}
//取得地址类型
short addrType = 0;
addrType = pHost->h_addrtype;
CString strAddrType = _T("地址类型:");
if (1 == addrType)
{
strAddrType += _T("AF_UNIX");
}
else if (2 == addrType)
{
strAddrType += _T("AF_INET");
}
else if (23 == addrType)
{
strAddrType += _T("AF_INET6");
}
//取得地址长度
CString strLength = _T("地址长度:");
strTemp.Format("%d", pHost->h_length);
strLength += strTemp;
//取得IP地址列表
char** pIP = pHost->h_addr_list;
char* ip = NULL;
CPtrArray ptrArrayIP;
CString strIPList = _T("IP地址列表:");
for (; *pIP != NULL; pIP ++)
{
ip = inet_ntoa(*(struct in_addr *)*pIP);
ptrArrayIP.Add(ip);
}
//取得IP地址列表
int ipCount = ptrArrayIP.GetSize();
for (int m = 0; m <ipCount; m ++)
{
strIPList += "\r\n";
strIPList += (char*)ptrArrayIP.GetAt(m);
}
//准备最后要显示的信息
CString strInfo = "主机信息如下:";
strInfo += "\r\n\r\n" + strHost/*主机名*/ + "\r\n\r\n" + strHostName/*主机别名*/ + "\r\n\r\n"\
+ strAddrType/*IP地址类型*/ + "\r\n\r\n" + strLength/*IP地址长度*/ + "\r\n\r\n"\
+ strIPList/*IP地址列表*/ + "\r\n";
//给显示信息的控件赋值
SetDlgItemText(IDC_EDIT_HOSTINFO2, strInfo);
//删除集合元素
strArray.RemoveAll();
ptrArrayIP.RemoveAll();
}