网站建设背景和目标,免费制作简历模板网站,微信开发文档官网,网站设计是怎么做的VC常用功能开发汇总#xff08;专栏文章列表#xff0c;欢迎订阅#xff0c;持续更新...#xff09;https://blog.csdn.net/chenlycly/article/details/124272585C软件异常排查从入门到精通系列教程#xff08;专栏文章列表#xff0c;欢迎订阅#xff0c;持续更新...常用功能开发汇总专栏文章列表欢迎订阅持续更新...https://blog.csdn.net/chenlycly/article/details/124272585C软件异常排查从入门到精通系列教程专栏文章列表欢迎订阅持续更新...https://blog.csdn.net/chenlycly/article/details/125529931C软件分析工具从入门到精通案例集锦专栏文章正在更新中...https://blog.csdn.net/chenlycly/article/details/131405795C/C基础与进阶专栏文章持续更新中...https://blog.csdn.net/chenlycly/category_11931267.html 在使用socket套接字去连接远端的服务器时需要使用IP和远端服务器建链不能直接使用域名但我们配置服务器地址时有时需要设置域名这需要我们在代码中添加域名解析的模块在连接服务器之前将域名解析成IP地址。 1、域名解析的完整流程 经常有朋友询问使用DNS系统查询IP的完整流程这里我们普及一下这一过程。DNS服务器大致分为三种类型根DNS服务器、顶级域DNS服务器和权威DNS服务器其中顶级域DNS服务器主要负责诸如com、org、net、edu、gov 等顶级域名。 根DNS服务器存储了所有顶级域DNS服务器的 IP 地址可以通过根服务器找到顶级域服务器比如百度的域名www.baidu.com根服务器会返回所有维护 com 这个顶级域服务器的 IP 地址。然后你任选其中一个顶级域服务器发送请求该顶级域服务器拿到域名后能够给出负责当前域的权威服务器地址。以 百度的域名为例顶级域服务器将返回所有负责百度这个域的权威服务器地址。接着任选其中一个权威服务器地址查询“www.baidu.com”的具体 IP 地址最终权威服务器会返回给你具体的 IP 地址。此外本地 DNS 服务器是具有缓存功能的通常两天内的记录都会被缓存。 所以通过DNS系统查询域名对应的 IP 的具体步骤可以总结为 ① 操作系统先查本地 hosts文件 中是否有记录如果有则直接返回相对应映射的IP地址。② 如果本地hosts文件中没有配置则主机向自己的本地DNS服务器发送查询报文如果本地DNS服务器缓存中有将直接返回结果。③ 如果本地服务器缓存中没有则从内置在内部的根DNS服务器列表全球13台固定的IP地址中选一个发送查询报文。④ 根服务器解析域名中的后缀名告诉本地服务器负责该后缀名的所有顶级服务器列表。⑤ 本地服务器选择其中一个顶级域服务器发送查询请求顶级域服务器拿到域名后继续解析返回对应域的所有权威服务器列表。⑥ 本地服务器再向返回的权威服务器发送查询报文最终会从某一个权威服务器上得到具体的 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;
}