SockDB Windows 版
Linux版同様、次のような機能を実現します
1.ローカルホスト名を表示する
2.起動引数がないとき:ローカルホスト名に設定されているIPアドレスを表示する
3.起動引数にドメイン名(FQDN)を指定したとき:ドメイン名に設定されている
IPアドレスを表示する

プロジェクトの作成
ファイル→新規作成→VisualC++→空のプロジェクト
プロジェクト名:SockDB
「ソリューションのディレクトリを作成する」のチェックを外す。
プラットホームは64bits(x64)とする。

プロジェクト→既存の項目の追加を選びstdThread.cpp, stdThread.h を追加します。
Linux版からSockDB.cppをコピーし、既存の項目の追加で追加します。

これでプロジェクトをビルドしてみるとエラーがいくつか出ますので
出たエラーをつぶしていきましょう。

error C4996: ‘sprintf’: This function or variable may be unsafe.
sprintfにバッファオーバーランの脆弱性があるのでsprintf_sを使うか
_CRT_SECURE_NO_WARNINGSをdefineするというエラー
ここでは、Linuxとの互換性を優先することにし、C4996警告を抑制するように
します。次のようなdefineをSockDB.cppに追加します。

#ifdef _MSC_VER // Windowsのとき #define DISABLE_C4996 __pragma(warning(push)) __pragma(warning(disable:4996)) #define ENABLE_C4996 __pragma(warning(pop)) #else // Linuxのとき #define DISABLE_C4996 #define ENABLE_C4996 #endif

これでビルドは通りますが、動かしてみるとgethostnameでエラーになります。
ところが、エラー番号が0でどんなエラーが発生しているのかわかりません。
Windowsの場合ソケットのエラーはerrnoではなくWSAGetLastError()を使用します。

WSAGetLastError()でWSANOTINITIALISED (10093)エラーが出ていることがわかります。
これは、WindowsではソケットAPIを使用する場合Winsock DLLの初期化を行う
必要があるということを示しています。
プログラム開始時に初期化、終了時にWinsock DLLの使用終了を実施します。

以上がこのプログラム(SockDB)でのLinuxとWindowsの違いです。
以降作成するプログラムでも同様ですので、覚えておきましょう。
SockDB.cppは次のようになります

#include “stdThread.h” #ifdef _MSC_VER // Windowsのとき #define DISABLE_C4996 __pragma(warning(push)) __pragma(warning(disable:4996)) #define ENABLE_C4996 __pragma(warning(pop)) #else // Linuxのとき #define DISABLE_C4996 #define ENABLE_C4996 #endif // WinSock DLLの初期化、終了処理を行う関数の宣言 BOOL InitSocketLib(); BOOL UninitSocketLib(); void GetHostName(); void GetHostAddress(LPSTR pszCurHost); int main(int argc, char *argv[]) { int iRet = -1; LPSTR pszCurHost = NULL; if (InitSocketLib() == FALSE) // WinSock DLL の初期化 goto L_END; // 起動引数のチェック if (argc == 2) pszCurHost = argv[1]; // ドメイン名が指定された GetHostName(); // ローカルホスト名の取得 GetHostAddress(pszCurHost); // アドレスの取得 UninitSocketLib(); // WinSock DLL の終了 iRet = 0; L_END: return(iRet); } #define VERSION_RECESTED MAKEWORD(2, 0) // 必要とするWINSOCK.DLL(WSOCK32.DLL のバージョン) ///////////////////////////////////////////////// // function // ソケットライブラリのロード // parameter // なし // retun // なし ///////////////////////////////////////////////// BOOL InitSocketLib() { WORD wVersionRequested; // バージョン情報格納エリア(windows) WSADATA wsaData; // WinSock 情報格納エリア(windows) BOOL fRet; wVersionRequested = VERSION_RECESTED; // 初期化処理 fRet = (WSAStartup(wVersionRequested, &wsaData) == 0) ? TRUE : FALSE; return(fRet); } ///////////////////////////////////////////////// // function // ソケットライブラリの開放 // parameter // なし // retun // なし ///////////////////////////////////////////////// BOOL UninitSocketLib() { BOOL fRet; fRet = (WSACleanup() == 0) ? TRUE : FALSE; // 解放処理 return(fRet); } ///////////////////////////////////////////////// // function // ローカルホスト名の取得 // parameter // なし // retun // なし ///////////////////////////////////////////////// void GetHostName() { char szHostName[NI_MAXHOST]; // ホスト名格納エリア char szMsg[NI_MAXHOST]; // ローカルホスト名の取得 DISABLE_C4996 if (gethostname(szHostName, sizeof(szHostName)) == SOCKET_ERROR) sprintf(szMsg, “Err: %d”, WSAGetLastError()); else sprintf(szMsg, “%s”, szHostName); ENABLE_C4996 fprintf(stderr, “%s\n”, szMsg); } ///////////////////////////////////////////////// // function // ホスト名からIPアドレスを取得する // ホスト名がNULLのときはローカルホスト名を使用する // parameter // LPSTR pszCurHost [in]ホスト名/NULL // retun // なし //———————————————- void GetHostAddress(LPSTR pszCurHost) { char szHostName[NI_MAXHOST]; // ホスト名格納エリア addrinfo hints, *pres = NULL, *pTemp = NULL; char szHostAddr[NI_MAXHOST]; // アドレス格納エリア int iCount = 1; // ホスト名をszHostNameに格納 if (pszCurHost != NULL) { DISABLE_C4996 strcpy(szHostName, pszCurHost); ENABLE_C4996 } else { if (gethostname(szHostName, sizeof(szHostName)) == SOCKET_ERROR) goto L_END; } // hintsの初期化 memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; // IPv4, IPv6ともに列挙対象とする // hintに従ってアドレス情報を取得する if (getaddrinfo(szHostName, NULL, &hints, &pres) != 0) goto L_END; // 順番にpresの中に格納されている情報を表示する pTemp = pres; while (pTemp != NULL) { // NI_NUMERICHOST 数値形式のホスト名(IPアドレス) if (getnameinfo(pTemp->ai_addr, (socklen_t)pTemp->ai_addrlen, szHostAddr, sizeof(szHostAddr), NULL, 0, NI_NUMERICHOST) == 0) { fprintf(stderr, “%d family:%2d Address:%s\n”, iCount, pTemp->ai_family, szHostAddr); } pTemp = pTemp->ai_next; // 次の情報へ移動 iCount++; } freeaddrinfo(pres); // 取得した情報を破棄 L_END: return; }

hintsの初期化で
hints.ai_family = AF_UNSPEC;
を指定すると、対象がすべてのファミリつまりIPv4, IPv6になります。
AF_INETを指定するとIPv4, AF_INET6を指定するとIPV6のみが対象となります。

if(getaddrinfo(szHostName, NULL, &hints, &pres) != 0)
と、ホスト名のみを指定すると指定したホストのアドレス情報が
ヒントに指定した条件でpresに格納されます。

if (getnameinfo(pTemp->ai_addr, (socklen_t)pTemp->ai_addrlen,
szHostAddr, sizeof(szHostAddr), NULL, 0, NI_NUMERICHOST) == 0)
とNI_NUMERICHOSTを指定するとpTemp->ai_addrに格納されている
IPアドレス(バイナリ)が数値形式でszHostAddrに格納されます。
pTemp->ai_addrはIPv4のときsockaddr_inで、IPv6のときsockaddr_in6に
なります。

引数にwww.oji-koji.comを指定して動かすとIPv4とIPv6をDNS
サーバに登録してありますので、ちゃんと取得できています
(*)AF_INET6の値がLinuxとWindowsで異なることに注意
条件文などで直接値を使用してはだめですね

C:\projects\SockDB\x64\Debug>SockDB www.oji-koji.com
ShimodaWindows
1 family:23 Address:2001:e42:102:1535:160:16:119:222
2 family: 2 Address:160.16.119.222

【参考】
プロジェクトSockDB for Windows(zip)
引数にドメイン名、サービス名を指定すると
IPアドレスとポート番号を表示する