网络编程实验1_(8)获得给定域名的IP地址(C++代码)
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
#include<WinSock2.h>
#include<string>
#include<Windows.h>
#pragma comment(lib,"Ws2_32.lib")
using namespace std;
int main()
{
WSADATA wsaData;
string name;
struct hostent* hostInfo;
struct in_addr addr;
if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData) ){
cout<<"网络库启动失败"<<endl;
return 1;
}
cout << "请输入你要查找的域名" << endl;
/*
c_str()函数返回一个指向正规C字符串的指针, 内容与本string串相同
这个数组的数据是临时的,当有一个改变这些数据的成员函数被调用后,其中的数据就会失效。
因此要么现用先转换,要么把它的数据复制到用户自己可以管理的内存中
*/
// 这个inet_ntoa调用完之后必须立即将值输出,不能连续调用,后面一次调用会覆盖前一次的结果
// u_long 就是无符号长整型
// addr是我在前面定义的in_addr类型的结构体,这个结构体的成员变量是一个联合体,联合体的特点就是一次只能有一个成员有值
// 定义的联合体变量是S_un,可以通过转定义发现这个变量是四字节的,且这个联合体中的S_addr,也就是S_un.S_addr是ULONG类型
// 所以我们可以把IP地址通过强制类型转换转成u_long类型,并赋给S_un.S_addr,由于我定义的in_addr结构体的变量名为addr,
// 因此就是赋给addr.s_addr,最后再用inet_ntoa转换成点分十进制的字符串,而且要记得不要连续使用这个函数,它会覆盖上一次的值
while (cin >> name) {
hostInfo = gethostbyname(name.c_str());
if (hostInfo != NULL) {
int i = 0;
while (hostInfo->h_addr_list[i] != 0) {
addr.s_addr = *(u_long*)hostInfo->h_addr_list[i++];
cout << "IP 地址" << i << ":" << inet_ntoa(addr) << endl;
}
}
}
// 这个WSACleanup尤其不要忘记,最好是养成好习惯,每写一次WSAStartup就在后面补一个WSACleanup()
WSACleanup();
system("pause");
return 0;
}
基本上要注意的地方我都在注释里写清楚了。
但是,还要提一点的是,第一行的
#define _WINSOCK_DEPRECATED_NO_WARNINGS
这个是干嘛用的呢?
如果不加这一行,就会出现
根据提示,应该使用getaddrinfo()或者GetAddrInfoW()来代替我们使用的gethostbyname()
正如我在写代码之前参照的msdn上的文档一样,以下是我从msdn上找到的原文(翻译之后的)
注意,gethostbyname函数已经被getaddrinfo函数的引入所废弃。建议创建WindowsSocket 2应用程序的开发人员使用getaddrinfo函数而不是gethostbyname。
那么既然是这样,那就没什么好奇怪的了,
正如我每次写c++程序时,前面都要加上一个#define _CRT_SECURE_NO_WARNINGS一样,
Visual studio总会有一些不是错误的错误,
接着看后面那句“or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings”
这时,答案已经呼之欲出了,
直接在开头加上一个
#define _WINSOCK_DEPRECATED_NO_WARNINGS