windows下获取IP地址的两种方法;
一种可以获取IPv4和IPv6,但是需要WSAStartup;
一种只能取到IPv4,但是不需要WSAStartup;
如下:
方法一:(可以获取IPv4和IPv6)
1 #define _WINSOCK_DEPRECATED_NO_WARNINGS 2 #include <Winsock2.h> 3 #include <stdio.h> 4 #include <iostream> 5 #include <cstring> 6 #include<ws2tcpip.h> 7 #pragma comment(lib, "ws2_32.lib ") //linking to the library 8 using namespace std; 9 int get_ip() 10 { 11 struct addrinfo *ailist, *aip; 12 struct addrinfo hint; 13 struct sockaddr_in6 *sinp6; 14 PHOSTENT hostinfo; 15 char hostname[255] = {0}; //主机名 16 char *port = "3294"; //端口号 17 const char *addr; 18 int ilRc; 19 gethostname(hostname, sizeof(hostname)); 20 if((hostinfo = gethostbyname(hostname)) == NULL) //获得本地ipv4地址 21 { 22 errno = GetLastError(); 23 fprintf(stderr,"gethostbyname Error:%d ", errno); 24 return 1; 25 } 26 LPCSTR ip; 27 while(*(hostinfo->h_addr_list) != NULL) //输出ipv4地址 28 { 29 ip = inet_ntoa(*(struct in_addr *) *hostinfo->h_addr_list); 30 printf("ipv4 addr = %s ", ip); 31 hostinfo->h_addr_list++; 32 } 33 hint.ai_family = AF_INET6; //hint 的限定设置 34 hint.ai_socktype = SOCK_STREAM; //这里可是设置 socket type 比如 SOCK_DGRAM 35 hint.ai_flags = AI_PASSIVE; // flags 的标志很多。常用的有AI_CANONNAME; 36 hint.ai_protocol = 0; //设置协议 一般为0,默认 37 hint.ai_addrlen = 0; //下面不可以设置,为0,或者为NULL 38 hint.ai_canonname = NULL; 39 hint.ai_addr = NULL; 40 hint.ai_next = NULL; 41 ilRc = getaddrinfo(hostname, port, &hint, &ailist); //通过主机名获得地址信息 42 if (ilRc < 0) 43 { 44 char str_error[100]; 45 strcpy(str_error, (char *)gai_strerror(errno)); 46 printf("str_error = %s", str_error); 47 return 0; 48 } 49 if(ailist == NULL) 50 { 51 printf("sorry not find the IP address,please try again "); 52 } 53 for (aip = ailist; aip != NULL; aip = aip->ai_next) //显示获取的信息 54 { 55 aip->ai_family == AF_INET6; 56 sinp6 = (struct sockaddr_in6 *)aip->ai_addr; //为什么是for 循环 ,先向下看 57 int i; 58 printf("ipv6 addr = "); 59 for(i = 0; i < 16; i++) 60 { 61 if(((i-1)%2) && (i>0)) 62 { 63 printf(":"); 64 } 65 printf("%02x",sinp6->sin6_addr.u.Byte[i]); 66 } 67 printf(" "); 68 printf(" "); 69 } 70 while(1); 71 } 72 int main(){ 73 74 WORD wVersionRequested; 75 WSADATA wsaData; 76 int err; 77 wVersionRequested = MAKEWORD( 1, 1 ); 78 err = WSAStartup( wVersionRequested, &wsaData );//initiate the ws2_32.dll and match the version 79 if ( err != 0 ) 80 { 81 return 0; 82 } 83 if ( LOBYTE( wsaData.wVersion ) != 1 || //if the version is not matched ,then quit and terminate the ws3_32.dll 84 HIBYTE( wsaData.wVersion ) != 1 ) 85 { 86 WSACleanup( ); 87 return 0; 88 } 89 get_ip(); 90 WSACleanup( ); 91 return 0; 92 }
方法二:(只能取到IPv4)
1 //#define _WINSOCK_DEPRECATED_NO_WARNINGS 2 #include <WinSock2.h> 3 #include <Iphlpapi.h> 4 #include <iostream> 5 using namespace std; 6 #pragma comment(lib,"Iphlpapi.lib") //需要添加Iphlpapi.lib库 7 //#pragma comment(lib, "ws2_32.lib") 8 9 int main(int argc, char* argv[]) 10 { 11 //PIP_ADAPTER_INFO结构体指针存储本机网卡信息 12 PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO(); 13 //得到结构体大小,用于GetAdaptersInfo参数 14 unsigned long stSize = sizeof(IP_ADAPTER_INFO); 15 //调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量 16 int nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize); 17 //记录网卡数量 18 DWORD netCardNum = 0; 19 GetNumberOfInterfaces(&netCardNum); 20 cout << "网卡数量:" << netCardNum<< endl; netCardNum = 0; 21 //记录每张网卡上的IP地址数量 22 int IPnumPerNetCard = 0; 23 if (ERROR_BUFFER_OVERFLOW == nRel) 24 { 25 //如果函数返回的是ERROR_BUFFER_OVERFLOW 26 //则说明GetAdaptersInfo参数传递的内存空间不够,同时其传出stSize,表示需要的空间大小 27 //这也是说明为什么stSize既是一个输入量也是一个输出量 28 //释放原来的内存空间 29 delete pIpAdapterInfo; 30 //重新申请内存空间用来存储所有网卡信息 31 pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize]; 32 //再次调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量 33 nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize); 34 } 35 if (ERROR_SUCCESS == nRel) 36 { 37 //输出网卡信息 38 //可能有多网卡,因此通过循环去判断 39 while (pIpAdapterInfo) 40 { 41 cout << "网卡序号:" << ++netCardNum <<" "<<pIpAdapterInfo->Index << endl; 42 cout << "网卡名称:" << pIpAdapterInfo->AdapterName << endl; 43 cout << "网卡描述:" << pIpAdapterInfo->Description << endl; 44 cout << "网卡类型:"; 45 switch (pIpAdapterInfo->Type) 46 { 47 case MIB_IF_TYPE_OTHER: cout << "OTHER" << endl; break; 48 case MIB_IF_TYPE_ETHERNET: cout << "ETHERNET" << endl; break; 49 case MIB_IF_TYPE_TOKENRING: cout << "TOKENRING" << endl; break; 50 case MIB_IF_TYPE_FDDI: cout << "FDDI" << endl; break; 51 case MIB_IF_TYPE_PPP: cout << "PPP" << endl; break; 52 case MIB_IF_TYPE_LOOPBACK: cout << "LOOPBACK" << endl; break; 53 case MIB_IF_TYPE_SLIP: cout << "SLIP" << endl; break; 54 default: cout << "" << endl; break; 55 } 56 cout << "网卡MAC地址:"; 57 for (DWORD i = 0; i < pIpAdapterInfo->AddressLength; i++) 58 if (i < pIpAdapterInfo->AddressLength - 1) 59 { 60 printf("%02X-", pIpAdapterInfo->Address[i]); 61 } 62 else 63 { 64 printf("%02X ", pIpAdapterInfo->Address[i]); 65 } 66 cout << "网卡IP地址如下:" << endl; 67 IPnumPerNetCard = 0; 68 //可能网卡有多IP,因此通过循环去判断 69 IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList); 70 do 71 { 72 cout << "该网卡上的IP数量:" << ++IPnumPerNetCard << endl; 73 cout << "IP 地址:" << pIpAddrString->IpAddress.String << endl; 74 cout << "子网掩码:" << pIpAddrString->IpMask.String << endl; 75 cout << "网关地址:" << pIpAdapterInfo->GatewayList.IpAddress.String << endl; 76 pIpAddrString = pIpAddrString->Next; 77 } while (pIpAddrString); 78 pIpAdapterInfo = pIpAdapterInfo->Next; 79 cout << "--------------------------------------------------------------------" << endl; 80 } 81 82 } 83 //释放内存空间 84 if (pIpAdapterInfo) 85 { 86 delete pIpAdapterInfo; 87 } 88 return 0; 89 }