Call gethostbyname to implement domain name resolution (source code attached)

Summary of the development of common functions of VC++ (list of column articles, welcome to subscribe, continuous updates...) icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585 C++ software anomaly troubleshooting series of tutorials from entry to proficiency (list of column articles) , welcome to subscribe and continue to update...) icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931 C++ software analysis tools from entry to mastery case collection (column article is being updated...) icon-default.png?t=N7T8https:/ /blog.csdn.net/chenlycly/article/details/131405795 C/C++ basics and advanced (column article, continuously updated...) icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html        Using socket When using a socket to connect to a remote server, you need to use IP to establish a link with the remote server. You cannot use the domain name directly. However, when we configure the server address, we sometimes need to set the domain name. This requires us to add a domain name resolution module to the code. Resolve the domain name into an IP address before connecting to the server.

1. Complete process of domain name resolution

       Friends often ask about the complete process of using the DNS system to query IP. Here we will popularize this process. DNS servers are roughly divided into three types: root DNS servers, top-level domain DNS servers, and authoritative DNS servers. Top-level domain DNS servers are mainly responsible for top-level domain names such as com, org, net, edu, gov, etc.

       The root DNS server stores the IP addresses of all top-level domain DNS servers. The top-level domain server can be found through the root server. For example, Baidu's domain name www.baidu.com, the root server will return the IP addresses of all servers that maintain the com top-level domain. Then you choose one of the top-level domain servers to send a request. After getting the domain name, the top-level domain server can give the authoritative server address responsible for the current domain. Taking Baidu's domain name as an example, the top-level domain server will return all authoritative server addresses responsible for Baidu's domain. Then select one of the authoritative server addresses to query the specific IP address of "www.baidu.com". Finally, the authoritative server will return you the specific IP address. In addition, the local DNS server has a caching function, and records within two days are usually cached.

       Therefore, the specific steps for querying the IP corresponding to a domain name through the DNS system can be summarized as:

  • ① The operating system first checks whether there is a record in the local hosts file. If so, it directly returns the corresponding mapped IP address.
  • ② If there is no configuration in the local hosts file, the host sends a query message to its local DNS server. If there is one in the local DNS server cache, the result will be returned directly.
  • ③ If it is not found in the local server cache, select one from the built-in root DNS server list (13 in the world, fixed IP address) to send the query message.
  • ④ The root server resolves the suffix name in the domain name and tells the local server a list of all top-level servers responsible for the suffix name.
  • ⑤ The local server selects one of the top-level domain servers to send a query request. After getting the domain name, the top-level domain server continues to parse and returns a list of all authoritative servers in the corresponding domain.
  • ⑥ The local server then sends a query message to the returned authoritative server, and finally obtains a specific IP address from an authoritative server.
  • ⑦ The host returns the result IP.

2. Call gethostbyname to initiate domain name resolution       

       So how to resolve domain names into IP addresses? In fact, it is very simple. Just call the system API function gethostbyname to achieve it. Note that the gethostbyname function may cause short-term congestion. The function will first go to the DNS server configured on the network card to query the IP address corresponding to the domain name. If the local DNS cannot be queried, it will go to the remote DNS server to query, so it may It will be more time consuming.

       Therefore, we need to place the code that calls the gethostbyname function in a new thread, and then deliver the IP information to the main thread after it is parsed. The relevant code is as follows:

// 域名解析线程函数
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;
}

Guess you like

Origin blog.csdn.net/chenlycly/article/details/133493511