﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Figo Yao | AI-Hack-Thinking...</title><link>http://www.cppblog.com/figoyao/</link><description>我也很想让世界变得更好，可是上帝却不开放源代码。</description><language>zh-cn</language><lastBuildDate>Tue, 09 Jun 2026 21:45:38 GMT</lastBuildDate><pubDate>Tue, 09 Jun 2026 21:45:38 GMT</pubDate><ttl>60</ttl><item><title>Windows网络编程技术[一]</title><link>http://www.cppblog.com/figoyao/archive/2010/04/25/113533.html</link><dc:creator>Figo</dc:creator><author>Figo</author><pubDate>Sun, 25 Apr 2010 12:29:00 GMT</pubDate><guid>http://www.cppblog.com/figoyao/archive/2010/04/25/113533.html</guid><wfw:comment>http://www.cppblog.com/figoyao/comments/113533.html</wfw:comment><comments>http://www.cppblog.com/figoyao/archive/2010/04/25/113533.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/figoyao/comments/commentRss/113533.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/figoyao/services/trackbacks/113533.html</trackback:ping><description><![CDATA[<p>作者：<a href="http://www.figoyao.com/" mce_href="http://www.figoyao.com" target="_blank">Figo</a><br mce_bogus="1"></p>
<p>从今天起，我们开始Windows平台下网络编程的学习。本篇主要讲解网络基础知识和本地主机网络相关信息查看涉及的API使用：<br>
<img src="http://www.figoyao.com/blog/wp-content/uploads/2010/04/IP-View.jpg" class="alignnone size-full wp-image-1355" title="IP view" mce_src="http://www.figoyao.com/blog/wp-content/uploads/2010/04/IP-View.jpg" alt="IP view" height="237" width="401"></p>
<p>在开始进入后面的实际编程之前，首先需要掌握一些网络基本知识：如TCP/IP协议中网络分为层，应用层协议都有哪些等等。因为时间关系，我不可能
巨细无遗的把所有知识都说明，所以更多的还要靠自己去<a href="http://www.google.com/" mce_href="http://www.google.com/" target="_blank">Google</a>和<a href="http://book.douban.com/subject/1088054/" mce_href="http://book.douban.com/subject/1088054/" target="_blank">看书</a>。</p>
<p>在Windows中，获取和设定本地网络配置信息的API集是<a href="http://www.google.com/search?q=IP+Helper" mce_href="http://www.google.com/search?q=IP+Helper" target="_blank">IP
Helper</a>，下面我以GetIfTable函数为例讲解它们的用法，其他函数的使用大同小异。</p>
<pre>[code lang="cpp"]<br>//...figoyao.com<br>//适配器信息结构定义<br>typedef struct _FADAPTER_INFO<br>{<br>	//接口列表次序<br>	DWORD dwOrder;<br><br>	//接口内部索引号<br>	DWORD dwIndex;<br>	//接口名称描述<br>	char szName[MAX_INTERFACE_NAME_LEN];<br>	//接口类型[本地回路/无线网卡/以太网卡/]<br>	char szAdapterType[64];<br>	//接口速度[Mbps为单位]<br>	DWORD dwSpeed_Mbps;<br><br>	//物理地址FF-FF-FF-FF-FF-FF<br>	char szMAC_Addr[32];<br>	//连接状态信息<br>	char szOperStatus[64];<br><br>	//发送和接收数据[bytes]<br>	DWORD dwOUTData;<br>	DWORD dwINData;<br><br>	//IP地址和子网掩码<br>	char szIP[32];<br>	char szSubMask[32];<br><br>}FADAPTER_INFO,*PFADAPTER_INFO;<br>[/code]</pre>
<p>下面的代码片段是获取适配器信息过程：</p>
<pre>[code lang="cpp"]<br>//...figoyao.com<br>//获取网卡详细信息<br>				PMIB_IFTABLE pstIfTable = NULL;<br>				ULONG ulIfTable = 0;<br>				GetIfTable(NULL,&amp;ulIfTable,TRUE);<br>				pstIfTable = (PMIB_IFTABLE)MALLOC(ulIfTable);<br>				if (NULL == pstIfTable)<br>				{<br>					MessageBox(hwnd,"(PMIB_IFTABLE)MALLOC(ulIfTable)失败","错误",MB_OK|MB_ICONERROR);<br>					SendMessage(hwnd,WM_CLOSE,0,0);<br>				}<br>				DWORD dwGetIfTableRet = GetIfTable(pstIfTable,&amp;ulIfTable,TRUE);<br>				if (NO_ERROR == dwGetIfTableRet)<br>				{<br>					if (pstIfTable-&gt;dwNumEntries != dwNumOfMac)<br>					{<br>						MessageBox(hwnd,"请报告你的Windows系统版本","错误",MB_OK|MB_ICONERROR);<br>						SendMessage(hwnd,WM_CLOSE,0,0);<br>					}<br>					for (DWORD dwCnt = 0;dwCnt &lt; pstIfTable-&gt;dwNumEntries;dwCnt++)<br>					{<br>						//索引号赋值[以0为起始]<br>						pstAdapterInfo[dwCnt]-&gt;dwOrder = dwCnt;<br>						pstAdapterInfo[dwCnt]-&gt;dwIndex = pstIfTable-&gt;table[dwCnt].dwIndex;<br>						pstAdapterInfo[dwCnt]-&gt;dwSpeed_Mbps = pstIfTable-&gt;table[dwCnt].dwSpeed/1000000;<br>						switch(pstIfTable-&gt;table[dwCnt].dwType)<br>						{<br>							//以太网适配器<br>							case IF_TYPE_ETHERNET_CSMACD:<br>							{<br>								sprintf(pstAdapterInfo[dwCnt]-&gt;szAdapterType,"以太网适配器");<br>							}<br>							break;<br><br>							//令牌环适配器<br>							case IF_TYPE_ISO88025_TOKENRING:<br>							{<br>								sprintf(pstAdapterInfo[dwCnt]-&gt;szAdapterType,"令牌环适配器");<br>							}<br>							break;<br><br>							//点到点协议适配器<br>							case IF_TYPE_PPP:<br>							{<br>								sprintf(pstAdapterInfo[dwCnt]-&gt;szAdapterType,"点到点协议适配器");<br>							}<br>							break;<br><br>							//An IEEE 802.11 wireless network interface<br>						case IF_TYPE_IEEE80211:<br>							{<br>								sprintf(pstAdapterInfo[dwCnt]-&gt;szAdapterType,"IEEE 802.11无线网络适配器");<br>							}<br>							break;<br><br>							//A tunnel type encapsulation network interface.<br>						case IF_TYPE_TUNNEL:<br>							{<br>								sprintf(pstAdapterInfo[dwCnt]-&gt;szAdapterType,"管道网络适配器");<br>							}<br>							break;<br><br>							//An ATM network interface.<br>						case IF_TYPE_ATM:<br>							{<br>								sprintf(pstAdapterInfo[dwCnt]-&gt;szAdapterType,"ATM网络适配器");<br>							}<br>							break;<br><br>							//A software loopback network interface.<br>						case IF_TYPE_SOFTWARE_LOOPBACK:<br>							{<br>								sprintf(pstAdapterInfo[dwCnt]-&gt;szAdapterType,"软件回路适配器");<br>							}<br>							break;<br><br>							//An IEEE 1394 (Firewire) high performance serial bus network interface.<br>						case IF_TYPE_IEEE1394:<br>							{<br>								sprintf(pstAdapterInfo[dwCnt]-&gt;szAdapterType,"IEEE 1394高性能串口适配器");<br>							}<br>							break;<br><br>						//光纤接口适配器<br>						case MIB_IF_TYPE_FDDI:<br>							{<br>								sprintf(pstAdapterInfo[dwCnt]-&gt;szAdapterType,"光纤接口适配器");<br>							}<br>							break;<br><br>							//串行适配器(Serial Line Interface Protocol)<br>						case MIB_IF_TYPE_SLIP:<br>							{<br>								sprintf(pstAdapterInfo[dwCnt]-&gt;szAdapterType,"串行适配器(Serial Line Interface Protocol)");<br>							}<br>							break;<br><br>						default:<br>							{<br>								sprintf(pstAdapterInfo[dwCnt]-&gt;szAdapterType,"其他类型适配器");<br>							}<br>							break;<br>						}<br><br>						//接口描述<br>						sprintf(pstAdapterInfo[dwCnt]-&gt;szName,"%d-&gt;%s",dwCnt+1,pstIfTable-&gt;table[dwCnt].bDescr);<br>						SendMessage(GetDlgItem(hwnd,IDC_CMB_ADAPTER),CB_ADDSTRING,0,(LPARAM)pstAdapterInfo[dwCnt]-&gt;szName);<br>						//物理地址<br>						if (0 == pstIfTable-&gt;table[dwCnt].dwPhysAddrLen)<br>						{<br>							sprintf(pstAdapterInfo[dwCnt]-&gt;szMAC_Addr,"00-00-00-00-00-00");<br>						}<br>						else<br>						{<br>							for (int j = 0;j &lt; pstIfTable-&gt;table[dwCnt].dwPhysAddrLen;j++)<br>							{<br>								char szMACStr[6] = "";<br>								if (j != pstIfTable-&gt;table[dwCnt].dwPhysAddrLen - 1)<br>								{<br>									sprintf(szMACStr,"%02x-",pstIfTable-&gt;table[dwCnt].bPhysAddr[j]);<br>								}<br>								else<br>								{<br>									sprintf(szMACStr,"%02x",pstIfTable-&gt;table[dwCnt].bPhysAddr[j]);<br>								}<br>								strcat(pstAdapterInfo[dwCnt]-&gt;szMAC_Addr,szMACStr);<br>							}<br>						}<br>						//收发数据[bytes]<br>						pstAdapterInfo[dwCnt]-&gt;dwINData = pstIfTable-&gt;table[dwCnt].dwInOctets;<br>						pstAdapterInfo[dwCnt]-&gt;dwOUTData = pstIfTable-&gt;table[dwCnt].dwOutOctets;<br>					}<br>				}<br>				else<br>				{<br>					char szTmpGetIfTableRet[32] = "";<br>					sprintf(szTmpGetIfTableRet,"[错误代码:%d]GetIfTable失败",dwGetIfTableRet);<br>					MessageBox(hwnd,szTmpGetIfTableRet,"错误",MB_OK|MB_ICONERROR);<br>					SendMessage(hwnd,WM_CLOSE,0,0);<br>				}<br>			}<br>			else<br>			{<br>				MessageBox(hwnd,"适配器接口数量获取失败","错误",MB_OK|MB_ICONERROR);<br>				SendMessage(hwnd,WM_CLOSE,0,0);<br>			}<br>//.............<br>[/code]</pre>
<p>外网IP获取部分，这里的方法是通过访问一个脚本获取，通过<a href="http://figoyao.com/pip.php" mce_href="http://figoyao.com/pip.php" target="_blank">http://figoyao.com/pip.php</a>即
可获取客户端IP地址，在这个地址失败后，尝试<a href="http://figo.oni.cc/pip.php" mce_href="http://figo.oni.cc/pip.php" target="_blank">http://figo.oni.cc/pip.php</a>，
如果依旧失败则不再尝试：</p>
<pre>[code lang="cpp"]<br>//...figoyao.com<br>/********************************************<br>*函数功能:<br>*获取本地主机在外网的IP地址<br>*入口参数:<br>*_out szPIP 接收外网IP的字符串地址<br>*<br>*返回值:<br>*成功:TRUE<br>*失败:FALSE<br>*<br>*注解:<br>*无<br>********************************************/<br>BOOL GetWANIPAddr(char *szPIP)<br>{<br>	//1.1.1.1<br>	if (NULL == szPIP)<br>	{<br>		return FALSE;<br>	}<br><br>	//检测网络状态<br>	char szUrl[] = "http://www.baidu.com";<br>	BOOL bState = InternetCheckConnection(szUrl,FLAG_ICC_FORCE_CONNECTION,0);<br>	if (FALSE == bState)<br>	{<br>		return FALSE;<br>	}<br><br>	//获取公网IP的网址及备份网址<br>	char szPIPUrl_Bak[] = "http://figoyao.com/pip.php";<br>	char szPIPUrl[] = "http://figo.oni.cc/pip.php";<br><br>	char szUserAgent[] = "figoyao/10.25 (Windows; U; Windows NT 6.4; zh-CN; rv:1.8.9) China/20121222";<br>	//创建会话<br>	HINTERNET hSession = InternetOpen(szUserAgent,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);<br>	if (NULL == hSession)<br>	{<br>		return FALSE;<br>	}<br><br>	HINTERNET hOpenUrl = NULL;<br>	char szRequesHeader[] = "Accept: text/html\r\n";<br><br>	hOpenUrl = InternetOpenUrl(hSession,szPIPUrl,szRequesHeader,strlen(szRequesHeader),\<br>		INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_RELOAD,0);<br><br>	if (NULL == hOpenUrl)<br>	{<br>		//如果打开第一个网址失败则尝试通过备份网址获取公网IP<br>		hOpenUrl = InternetOpenUrl(hSession,szPIPUrl_Bak,szRequesHeader,strlen(szRequesHeader),\<br>			INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_RELOAD,0);<br>		if (NULL == hOpenUrl)<br>		{<br>			if (hSession)<br>			{<br>				InternetCloseHandle(hSession);<br>			}<br>			return FALSE;<br>		}<br>		goto getpip;<br>	}<br><br>getpip:<br>	{<br>		//一次调用从服务器读取数据<br>		DWORD dwNumOfBufRead = 0;<br>		char lpGetIPBuf[32] = "";<br>		BOOL bReadFile = InternetReadFile(hOpenUrl,lpGetIPBuf,32,&amp;dwNumOfBufRead);<br><br>		//检测读取的地址是否符合要求<br>		if (dwNumOfBufRead &gt; 32 || FALSE == bReadFile)<br>		{<br>			if (hSession)<br>			{<br>				InternetCloseHandle(hSession);<br>			}<br>			if (hOpenUrl)<br>			{<br>				InternetCloseHandle(hOpenUrl);<br>			}<br>			return FALSE;<br>		}<br><br>	//	memset(szPIP,0,sizeof(szPIP));<br>		DWORD dwTmpIPLen = strlen(lpGetIPBuf);<br>		//接收的数据是以0+\r\n\r\n结尾,故减去5<br>		strncpy(szPIP,lpGetIPBuf,dwTmpIPLen-5);<br>	}<br><br>	if (hSession)<br>	{<br>		InternetCloseHandle(hSession);<br>	}<br>	if (hOpenUrl)<br>	{<br>		InternetCloseHandle(hOpenUrl);<br>	}<br>	return TRUE;<br>}<br>[/code]</pre>
<p>程序在Windows7测试未通过，但是控制台版本的没问题，究竟是何原因暂时没有深究。<strong>这次是使用VS2003编译的</strong>。</p>
<p>源码：<a href="http://figoyao.com/blog/file/HostInfo.rar" mce_href="http:///figoyao.com/blog/file/HostInfo.rar" target="_blank">点击
下载</a><br mce_bogus="1"></p>
<p>转载请注明出处：<a href="http://www.figoyao.com/blog/2010/04/25/1352" mce_href="http://www.figoyao.com/blog/2010/04/25/1352" target="_blank"><span id="sample-permalink">http://www.figoyao.com/blog/2010/04/25/1352</span></a><br mce_bogus="1"></p><img src ="http://www.cppblog.com/figoyao/aggbug/113533.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/figoyao/" target="_blank">Figo</a> 2010-04-25 20:29 <a href="http://www.cppblog.com/figoyao/archive/2010/04/25/113533.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>