IP Helper 함수들은 로컬 머신의 네트워크 설정을 검색 및 수정할 수 있도록 해주는 함수들이다. 또한 네트워크 설정이 변경된 경우, 이를 애플리케이션에게 통지해주는 기능도 제공한다.
#include <IPExport.h> #include <icmpapi.h> hostent* host = NULL; in_addr inaddr; inaddr.s_addr = ::inet_addr("155.230.29.10"); if (inaddr.s_addr == INADDR_NONE) { host = ::gethostbyname("155.230.29.10"); } else { host = ::gethostbyaddr((const char*)&inaddr, sizeof(inaddr), AF_INET); } if (host != NULL) { // ICMP 핸들을 생성한다. IPv6일 경우에는 Icmp6CreateFile()을 사용한다. HANDLE hICMP = ::IcmpCreateFile(); ICMP_ECHO_REPLY iep; iep.RoundTripTime = 0xFFFFFFFF; DWORD dw = ::IcmpSendEcho(hICMP, *((ULONG*)host->h_addr_list[0]), 0,0,NULL, &iep, sizeof(ICMP_ECHO_REPLY), 5000); cout << "RoundTripTime:" << iep.RoundTripTime << endl; ::IcmpCloseHandle(hICMP); }
플랫폼 SDK를 다운로드받은 다음, include 패스 잡아주고, iphlpapi.lib를 링크해줘야한다. 하지만 이렇게 해도 iphlpapi.dll에 IcmpCloseHandle이 없다고 에러가 났다. 짱난다. MSDN에 봐도 뭔가 일관성이 없고 - 다른 함수들은 iphlpapi.lib를 링크하라고 되어있는데, IcmpCloseHandle은 icmp.lib를 링크하라고 되어있는데다가, 플랫폼 SDK에 이런 라이브러리가 없다. - 문제가 많은 듯 하다.
GetAdaptersInfo 함수를 이용해 랜 카드의 IP 주소, MAC 주소, 현재 게이트웨이 등을 알아낼 수 있다.
DWORD GetAdaptersInfo( PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen );
typedef struct _IP_ADAPTER_INFO { struct _IP_ADAPTER_INFO* Next; DWORD ComboIndex; char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4]; char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4]; UINT AddressLength; BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH]; // MAC 주소 DWORD Index; UINT Type; UINT DhcpEnabled; PIP_ADDR_STRING CurrentIpAddress; IP_ADDR_STRING IpAddressList; // IP 주소 IP_ADDR_STRING GatewayList; IP_ADDR_STRING DhcpServer; BOOL HaveWins; IP_ADDR_STRING PrimaryWinsServer; IP_ADDR_STRING SecondaryWinsServer; time_t LeaseObtained; time_t LeaseExpires; } IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;
WMI의 Win32_NetworkAdapterConfiguration 클래스를 통해서도 비슷한 정보를 알아낼 수 있다. 참고로 IP만을 원하는 것이라면 다음과 같은 코드로도 알아낼 수 있다. 다만 루프백 주소(127.0.0.1)을 주의하기 바란다.
#include <iostream.h> #include <winsock.h> int main(int argc, char *argv[]) { WSAData wsaData; if (::WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) return 255; try { char ac[80] = {0,}; if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) { cerr << "Error " << WSAGetLastError() << " when getting local host name." << endl; throw; } cout << "Host name is " << ac << "." << endl; struct hostent *phe = gethostbyname(ac); if (phe == 0) { cerr << "Yow! Bad host lookup." << endl; throw; } for (int i=0; phe->h_addr_list[i] != 0; i++) { struct in_addr addr; memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr)); cout << "Address " << i << ": " << inet_ntoa(addr) << endl; } } catch (...) { cerr << "Something bad happen!" << endl; } ::WSACleanup(); return 0; }