c/c++實(shí)現(xiàn)獲取域名的IP地址
c/c++實(shí)現(xiàn)獲取域名的IP地址
// GetHostIP.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。
//
#include "stdafx.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")
int main(int argc, char **argv)
{
//-----------------------------------------
// Declare and initialize variables
/*
* WSADATA結(jié)構(gòu)被用來(lái)儲(chǔ)存調(diào)用AfxSocketInit全局函數(shù)返回的Windows Sockets初始化信息。
* 這個(gè)結(jié)構(gòu)被用來(lái)存儲(chǔ)被WSAStartup函數(shù)調(diào)用后返回的Windows Sockets數(shù)據(jù)。它包含Winsock.dll執(zhí)行的數(shù)據(jù)。
*/
WSADATA wsaData;
int iResult;
DWORD dwError; /*每個(gè)word為2個(gè)字節(jié)的長(zhǎng)度,DWORD 雙字即為4個(gè)字節(jié),每個(gè)字節(jié)是8位*/
int i = 0;
struct hostent *remoteHost; /*域名*/
char *host_name; /*主機(jī)名*/
struct in_addr addr; /*ip*/
char **pAlias;
// Validate the parameters
if (argc != 2) {
printf("usage: GetHostIP hostname\n");
return 1;
}
// 此處應(yīng)添加的程序如下
// 1. 當(dāng)初始化winsocket
iResult = WSAStartup(MAKEWORD(2,2),&wsaData);/* & 取地址*/
// 2. 檢查該socket是否初始化成功,即該socket是否等于0;如果初始化不成功,應(yīng)當(dāng)給出錯(cuò)誤報(bào)警,并結(jié)束程序。
if(iResult!=0){
printf("初始化失敗!\n");
return 1;
}
/////////////////結(jié)束///////////////////////////////////
host_name = argv[1];
printf("Calling gethostbyname with %s\n", host_name);
// 此處應(yīng)添加的程序如下
// 1. 利用函數(shù)gethostbyname(),獲取給定主機(jī)名的指針。
remoteHost = gethostbyname(host_name);
// 2. 應(yīng)當(dāng)熟悉該結(jié)構(gòu)指針的結(jié)構(gòu)
// 其中該函數(shù)申明如下:struct hostent* gethostbyname(const char *name)
// 此處應(yīng)添加的程序如下
// 1. 如果上面函數(shù)返回的主機(jī)結(jié)構(gòu)指針為空(NULL),則做如下處理:
// a. 利用函數(shù) int WSAGetLastError ( void ) 檢查當(dāng)前是否發(fā)生網(wǎng)絡(luò)錯(cuò)誤,
// b. 返回的發(fā)生的錯(cuò)誤類(lèi)型并作相應(yīng)的處理,比如,若沒(méi)有找到主機(jī)的錯(cuò)誤(此時(shí)該函數(shù)返回WSAHOST_NOT_FOUND)
if(remoteHost == NULL){
//printf("gethostbynameError:%d",WSAGetLastError());
return 1;
}else{
// 2. 如果返回的主機(jī)指針不為空,則做如下處理:
// a. 打印出如下參數(shù):主機(jī)名和IP地址,若該主機(jī)對(duì)應(yīng)于多個(gè)ip地址,應(yīng)當(dāng)分別列出。
printf("主機(jī)名:%s\n",remoteHost->h_name);
for(i=0;;i++){
if(remoteHost->h_addr_list[i]!=0)
{
/*從緩存中把 p 拷貝到addr中
*同時(shí)addr.S_un.Saddr
* in_addr ipAddr;
* ipAddr.S_un.S_addr = inet_addr("127.0.0.1");
* 就是把字符串形式的ip地址轉(zhuǎn)化為0xXXXXXXXX形式的地址格式。
*/
addr.s_addr = *(u_long*)remoteHost->h_addr_list[i];
printf("ip #%d:%s\n",i,inet_ntoa(addr)); /* inet_ntoa() 函數(shù)將網(wǎng)絡(luò)地址轉(zhuǎn)成二進(jìn)制的數(shù)字相關(guān)函數(shù):inet_aton, inet_ntoa */
}
/*
for(i=0;;i++){
char *p = remoteHost->h_addr_list[i];
if(p==NULL) break;
/*從緩存中把 p 拷貝到addr中
*同時(shí)addr.S_un.Saddr
* in_addr ipAddr;
* ipAddr.S_un.S_addr = inet_addr("127.0.0.1");
* 就是把字符串形式的ip地址轉(zhuǎn)化為0xXXXXXXXX形式的地址格式。
*
memcpy(&addr.S_un.S_addr,p,remoteHost->h_length);
printf("ip地址為:%s\n",inet_ntoa(addr));
*/
}
}
// 此處應(yīng)添加的程序如下
// 程序完成后應(yīng)當(dāng)適當(dāng)測(cè)試,需要進(jìn)行的測(cè)試如下:
// 1. 測(cè)試主機(jī)結(jié)構(gòu)指針獲取失敗
// 2. 測(cè)試包含多個(gè)IP地址的主機(jī)
// 3. 你能想到的任何可能出現(xiàn)的異常情況
/////////////////結(jié)束///////////////////////////////////
system("pause"); /*防止窗體關(guān)閉函數(shù)*/
return 0;
}
下面給大家詳細(xì)介紹下上面代碼的核心gethostbyname的詳細(xì)用法
使用這個(gè)東西,首先要包含2個(gè)頭文件:
#include <netdb.h> #include <sys/socket.h> struct hostent *gethostbyname(const char *name);
這個(gè)函數(shù)的傳入值是域名或者主機(jī)名,例如"www.google.com","wpc"等等。
傳出值,是一個(gè)hostent的結(jié)構(gòu)(如下)。如果函數(shù)調(diào)用失敗,將返回NULL。
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
};
解釋一下這個(gè)結(jié)構(gòu), 其中:
char *h_name 表示的是主機(jī)的規(guī)范名。例如www.google.com的規(guī)范名其實(shí)是www.l.google.com。
char **h_aliases 表示的是主機(jī)的別名。www.google.com就是google他自己的別名。有的時(shí)候,有的主機(jī)可能有好幾個(gè)別名,這些,其實(shí)都是為了易于用戶(hù)記憶而為自己的網(wǎng)站多取的名字。
int h_addrtype 表示的是主機(jī)ip地址的類(lèi)型,到底是ipv4(AF_INET),還是ipv6(AF_INET6)
int h_length 表示的是主機(jī)ip地址的長(zhǎng)度
int **h_addr_lisst 表示的是主機(jī)的ip地址,注意,這個(gè)是以網(wǎng)絡(luò)字節(jié)序存儲(chǔ)的。千萬(wàn)不要直接用printf帶%s參數(shù)來(lái)打這個(gè)東西,會(huì)有問(wèn)題的哇。所以到真正需要打印出這個(gè)IP的話,需要調(diào)用inet_ntop()。
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) :
這個(gè)函數(shù),是將類(lèi)型為af的網(wǎng)絡(luò)地址結(jié)構(gòu)src,轉(zhuǎn)換成主機(jī)序的字符串形式,存放在長(zhǎng)度為cnt的字符串中。
這個(gè)函數(shù),其實(shí)就是返回指向dst的一個(gè)指針。如果函數(shù)調(diào)用錯(cuò)誤,返回值是NULL。
下面是例程,有詳細(xì)的注釋。
#include <netdb.h>
#include <sys/socket.h>
int main(int argc, char **argv)
{
char *ptr,**pptr;
struct hostent *hptr;
char str[32];
/* 取得命令后第一個(gè)參數(shù),即要解析的域名或主機(jī)名 */
ptr = argv[1];
/* 調(diào)用gethostbyname()。調(diào)用結(jié)果都存在hptr中 */
if( (hptr = gethostbyname(ptr) ) == NULL )
{
printf("gethostbyname error for host:%s/n", ptr);
return 0; /* 如果調(diào)用gethostbyname發(fā)生錯(cuò)誤,返回1 */
}
/* 將主機(jī)的規(guī)范名打出來(lái) */
printf("official hostname:%s/n",hptr->h_name);
/* 主機(jī)可能有多個(gè)別名,將所有別名分別打出來(lái) */
for(pptr = hptr->h_aliases; *pptr != NULL; pptr++)
printf(" alias:%s/n",*pptr);
/* 根據(jù)地址類(lèi)型,將地址打出來(lái) */
switch(hptr->h_addrtype)
{
case AF_INET:
case AF_INET6:
pptr=hptr->h_addr_list;
/* 將剛才得到的所有地址都打出來(lái)。其中調(diào)用了inet_ntop()函數(shù) */
for(;*pptr!=NULL;pptr++)
printf(" address:%s/n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
break;
default:
printf("unknown address type/n");
break;
}
return 0;
}
另外附上獲得公網(wǎng)與內(nèi)網(wǎng)ip的代碼:
bool getPublicIp(string& ip)
{
int sock;
char **pptr = NULL;
struct sockaddr_in destAddr;
struct hostent *ptr = NULL;
char destIP[128];
sock = socket(AF_INET,SOCK_STREAM,0);
if( -1 == sock ){
perror("creat socket failed");
return false;
}
bzero((void *)&destAddr,sizeof(destAddr));
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons(80);
ptr = gethostbyname("www.ip138.com");
if(NULL == ptr){
perror("gethostbyname error");
return false;
}
for(pptr=ptr->h_addr_list ; NULL != *pptr ; ++pptr){
inet_ntop(ptr->h_addrtype,*pptr,destIP,sizeof(destIP));
printf("addr:%s\n",destIP);
ip = destIP;
return true;
}
return true;
}
獲取內(nèi)網(wǎng)IP
int getlocalip(char* outip)
{
#ifndef WIN32
int i=0;
int sockfd;
struct ifconf ifconf;
char buf[512];
struct ifreq *ifreq;
char* ip;
//初始化ifconf
ifconf.ifc_len = 512;
ifconf.ifc_buf = buf;
strcpy(outip,"127.0.0.1");
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0))<0)
{
return -1;
}
ioctl(sockfd, SIOCGIFCONF, &ifconf); //獲取所有接口信息
close(sockfd);
//接下來(lái)一個(gè)一個(gè)的獲取IP地址
ifreq = (struct ifreq*)buf;
for(i=(ifconf.ifc_len/sizeof(struct ifreq)); i>0; i--)
{
ip = inet_ntoa(((struct sockaddr_in*)&(ifreq->ifr_addr))->sin_addr);
if(strcmp(ip,"127.0.0.1")==0) //排除127.0.0.1,繼續(xù)下一個(gè)
{
ifreq++;
continue;
}
}
strcpy(outip,ip);
return 0;
#else
return 0;
#endif
}
上一篇:C++中strcpy函數(shù)的實(shí)現(xiàn)
欄 目:C語(yǔ)言
下一篇:深入淺析STL vector用法
本文標(biāo)題:c/c++實(shí)現(xiàn)獲取域名的IP地址
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/2661.html
您可能感興趣的文章
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)-用棧實(shí)現(xiàn)表達(dá)式求值的方法詳解
- 01-10使用OpenGL實(shí)現(xiàn)3D立體顯示的程序代碼
- 01-10深入理解C++中常見(jiàn)的關(guān)鍵字含義
- 01-10求斐波那契(Fibonacci)數(shù)列通項(xiàng)的七種實(shí)現(xiàn)方法
- 01-10C語(yǔ)言 解決不用+、-、&#215;、&#247;數(shù)字運(yùn)算符做加法
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類(lèi)算法
- 01-10深入全排列算法及其實(shí)現(xiàn)方法


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫(xiě)分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫(xiě)函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 04-02jquery與jsp,用jquery
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10delphi制作wav文件的方法
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改


