gethostbyname を呼び出してドメイン名解決を実装します (ソース コードが添付されています)。

VC++ の共通機能開発の概要 (コラム記事のリスト、購読歓迎、継続的な更新...) icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585 C++ ソフトウェア異常トラブルシューティング チュートリアル シリーズ入門から習熟まで(コラム記事一覧)、ぜひ購読して更新を続けてください...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931入門から習熟までのC++ソフトウェア解析ツール事例集(コラム)記事は更新中...) icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795 C/C++ の基礎と応用 (コラム記事、継続的に更新中...) icon-default.png?t=N7T8https://blog.csdn.net /chenlycly/category_11931267.html       ソケットの使用 ソケットを使用してリモート サーバーに接続する場合、IP を使用してリモート サーバーとのリンクを確立する必要があります。ドメイン名を直接使用することはできません。ただし、サーバー アドレスを設定するときに、場合によっては、ドメイン名を設定する必要があります。これには、コードにドメイン名解決モジュールを追加する必要があります。サーバーに接続する前に、ドメイン名を IP アドレスに解決します。

1. ドメイン名解決の完全なプロセス

       DNS システムを使用して IP をクエリする完全なプロセスについてよく友人に尋ねられますが、ここではこのプロセスを普及させていきます。DNSサーバーはルートDNSサーバー、トップレベルドメインDNSサーバー、権威DNSサーバーの3種類に大別され、トップレベルドメインDNSサーバーは主にcom、org、net、edu、などのトップレベルドメイン名を担当します。政府など

       ルート DNS サーバーには、すべてのトップレベル ドメイン DNS サーバーの IP アドレスが保存されます。トップレベル ドメイン サーバーは、ルート サーバーを通じて見つけることができます。たとえば、Baidu のドメイン名 www.baidu.com の場合、ルート サーバーは IP を返します。 com トップレベル ドメインを維持するすべてのサーバーのアドレス。次に、リクエストを送信するトップレベル ドメイン サーバーの 1 つを選択すると、ドメイン名を取得した後、トップレベル ドメイン サーバーは、現在のドメインを担当する権限のあるサーバー アドレスを与えることができます。Baidu のドメイン名を例にとると、トップレベル ドメイン サーバーは、Baidu のドメインを担当するすべての権威サーバー アドレスを返します。次に、権威サーバー アドレスの 1 つを選択して、「www.baidu.com」の特定の IP アドレスをクエリすると、最終的に権威サーバーから特定の IP アドレスが返されます。また、ローカルDNSサーバーにはキャッシュ機能があり、通常2日以内のレコードがキャッシュされます。

       したがって、DNS システムを通じてドメイン名に対応する IP を照会するための具体的な手順は次のように要約できます。

  • ① オペレーティングシステムは、まずローカルホストファイルにレコードがあるかどうかを確認し、レコードがあれば、対応するマッピングされた IP アドレスを直接返します。
  • ② ローカルホストファイルに設定がない場合、ホストはローカル DNS サーバーにクエリメッセージを送信し、ローカル DNS サーバーのキャッシュに設定があれば、結果を直接返します。
  • ③ ローカルサーバーキャッシュに見つからない場合は、内蔵ルートDNSサーバーリスト(世界13、固定IPアドレス)から1つを選択してクエリメッセージを送信します。
  • ④ ルート サーバーはドメイン名のサフィックス名を解決し、そのサフィックス名を担当するすべてのトップレベル サーバーのリストをローカル サーバーに伝えます。
  • ⑤ ローカル サーバーは、クエリ要求を送信するトップレベル ドメイン サーバーの 1 つを選択し、ドメイン名を取得した後、トップレベル ドメイン サーバーは解析を続け、対応するドメイン内のすべての権限のあるサーバーのリストを返します。
  • ⑥ ローカルサーバーは、返された権威サーバーにクエリメッセージを送信し、最終的に権威サーバーから特定の IP アドレスを取得します。
  • ⑦ ホストは結果の IP を返します。

2. gethostbyname を呼び出してドメイン名解決を開始します。       

       では、ドメイン名を IP アドレスに解決するにはどうすればよいでしょうか? 実際、これは非常に簡単で、システム API 関数 gethostbyname を呼び出すだけで実現できます。gethostbyname 関数は、短期間の輻輳を引き起こす可能性があることに注意してください。この関数は、まずネットワーク カードに設定されている DNS サーバーにアクセスして、ドメイン名に対応する IP アドレスをクエリします。ローカル DNS にクエリできない場合は、リモート DNS サーバーにクエリを実行するため、より時間がかかる場合があります。

       したがって、gethostbyname 関数を呼び出すコードを新しいスレッドに配置し、解析された IP 情報をメインスレッドに渡す必要があります。関連するコードは次のとおりです。

// 域名解析线程函数
UINT __stdcall QueryDomainThread( LPVOID pParam )
{
	char* lpszDomainName = (char*)pParam; 

	struct hostent *pHost = gethostbyname( lpszDomainName ); 
	if( NULL == pHost )  
	{   
		// ::PostMessage // 通知主线程域名解析失败
		return 0;   
	}

	if ( pHost->h_addr_list[0] != NULL ) 
	{ 
		u32 dwIP = (*(in_addr*)pHost->h_addr_list[0]).S_un.S_addr; 
		// ::PostMessage // 通知主线程域名解析成功,将解析出来的IP投递过去
	}  

	return 0; 
}

// 发起域名解析,创建新的线程去解析
LRESULT StartQueryDomain( char* lpszDomainName )
{
	// 此处不能直接将局部变量lpszDomainName传到线程函数中,因为启动线程的_beginthreadex返回时,线程函数不一定跑起来了
	// 所以最好搞一个成员变量或者全局变量,将lpszDomainName中的字符串拷贝下来,然后给_beginthreadex传递这个声明周期
	// 更长的变量
	strcpy( g_szMDomainName, lpszDomainName );

    // 线程函数QueryDomainThread的实现,上面已经给出
	HANDLE hThread= (HANDLE)_beginthreadex( NULL, 0, QueryDomainThread, (void*)g_szMDomainName, 0, NULL );
	if( hThread != NULL )
	{
		CloseHandle( hThread );
		return S_OK;
	}

	return S_FALSE;
}

おすすめ

転載: blog.csdn.net/chenlycly/article/details/133493511