答案:在VC++ 5.0中,MFC的WinInet类包装了相关的用于internet 客户机程序编程的win32 API函数。这样,无需了解winsock或TCP\IP的细节就可以编制出internet客户机程序。本文中,我们将探讨如何使用WinInet类来编写一个internet查询程序,该程序起名为“探路者”。该程序能使用各种协议来查询网络,包括古老的FINGER和WHOIS。
顾名思义,“探路者”用于探查一部internet服务器的情况,查看它能提供哪些服务。例如说,你知道某人的e-mail地址,假设是wang@eop.com,我们就可以通过该程序,尝试用各种办法建立到eop.com的链接,随后对该指定域依次采用WWW查询、FTP查询、GOPHER查询、FINGER查询和WHOIS查询。根据返回的结果,可以判断该域能提供哪些服务。此外,如果你想给自己的服务器起某个域名,你也可以通过本程序知道该域名是否已被采用。
一、查询程序界面的实现
本程序的用户界面将基于对话框来实现。建立界面的步骤如下:在developer studio中,
1、选择file-new…,高亮MFC appwizard(exe),在Project name栏内给程序取名为query ,单击ok。
2、在step-1中,单击dialog based,选English做为资源语言。单击next。
3、在step-2中,取消ActiveX Controls的选中标记。不要选择windows socket(该程序不直接调用socket函数),在对话框标题栏中键入“探路者”。
4、在step-3中,选择yes,please和As a ststically linked library
5、在step-4中,不要改变appwiard所生成的任何类名,appwizard结束后,我们准备着手编写程序的核心部分。appwizard建立了一个空的对话框,我们将从它的基础上开始工作。下面编辑对话框:
选resource view ,展开query resources-dialogs,双击IDD-QUERY-DIALOG 资源,下面编辑对话框:1、将OK按钮改为“查询主机”,右击该按钮,选择properties,将该按钮的ID名改为id-query。
2、将CANCEL按钮改为“结束查询”。
3、删除to do等静态文本。
4、将对话框增大到300像素宽
5、在对话框顶端增加一个编辑框,资源id名为IDC-HOST,将编辑框拉伸到最宽。
6、给编辑框增加一个名为“地址名”的标签。
7、将对话框拉伸到150像素高。
8、在对话框底部增加另一个编辑框,id名为IDC-OUT,将它拉伸到尽可能的大,填满对话框的剩余空间。
9、给该编辑框增加Multi-line,Horizontal scroll,Vertical scroll,Border,Read-only等特性。当用户单击“查询主机”按钮时,程序将使用各种方法查询网址。因此,需使用classwizard,把实现查询功能的代码链接到query按钮。
1、选view-classwizard。
2、选CQueryDlg类,主机名将由该类接受。
3、高亮ID-query,高亮右边列表栏里的BN-CLICKED。
4、按Add Fuction按钮,增加一个函数。
5、Class Wizard建议的名字为OnOk,将它改为OnQuery ,,单击ok
6、单击成员变量栏,准备将edit控制连接到对话框类的变量
7、高亮IDC-HOST并单击Add Variable。将把EDIT控制连接到对话框类的Cstring成员变量,名为m_host
8、类似以上步骤,将IDC-OUT链接到CString变量m_out点击ok关闭classwizard,剩下的工作是编写CQueryDlg::OnQuery()函数,它将使用m_host值进行查询并将结果输出到m_out变量。
二、编写代码,进行http查询
查询一个internet地址时,首先应尝试建立http链接。这是因为大量的地址都含有web页面。使用http建立链接的最简单的办法是使用winlnet类CInternetSession,并调用其成员函数OpenURL()。该函数将返回一个文件,我们在m_out中显示该文件的头几行文字。首先,在QueryDLG.CPP的开始加入以下行:
#include‘afxinet.h’这将定义访问Winlnet类的代码。由于本程序将访问大量的URLS,在CQueryDlg中增加一个名为TryURL的函数,它含有一个CString类的参数,名为URL,返回值为void。右击CQueryDLG类,选择Add Member function…。增加函数TryURL(),将它定义为protected类型。这个新函数将从CQueryDlg::OnQuery()中调用。在OnQuery()中增加以下代码:
void CQueryDlg::OnQuery()
{ const CString http = "http://";
UpdateData(TRUE);
m_out = "";
UpdateData(FALSE);
TryURL(http + m_host);
TryURL(http + "www." + m_host);
}UpdateData(TRUE)的调用将给m_host赋予用户定义的值。UpdateData(FALSE)语句将清空输出编辑框变量m_out的内容。接下来调用两次TryURL(),例如说,当用户输入microsoft.com,程序将首先试一试http://microsoft.com,然后试一试http://www.microsoft.com。以下是TryURL的代码。
void CQueryDlg::TryURL(CString URL)
{
CInternetSession session;
m_out+="正在链接"+URL+"\r\n";
UpdateData(FALSE);
CInternetFile* file=NULL;
try
{
file=(CInternetFile*)session.OpenURL(URL);
}
catch(CInternetException* pEx)
{
file=NULL;
pEx->Delete();
}
if(file)
{
m_out+="已建立链接。\r\n";
CString line;
for(int i=0;i<20&&file->ReadString(line);i++)
{
m_out+=line+"\r\n";
}
file->Close();
delete file;
}
else
{
m_out+="本地址没有发现http主机\r\n";
}
m_out+="------------------------------------------------------\r\n";
UpdateData(FALSE);
}下面,我们对以上代码进行逐段分析。首先,建立一个internet区,这要定义一个CInternetSession的对象。其构造函数的原形如下:
CInternetSession( LPCTSTR pstrAgent = NULL, DWORD dwContext = 1, DWORD dwAccessType = INTERNET_OPEN_TYPE_PRECONFIG, LPCTSTR pstrProxyName = NULL, LPCTSTR pstrProxyBypass = NULL, DWORD dwFlags = 0 );这需要定义很多参数,但是,本程序都使用缺省值,即“=”号后的值。CInternetSession构造函数参数说明如下:
LPCTSTR pstrAgent-应用程序名,如果为NULL,它将替你填入你在AppWizard中给定的程序名。
DWORD dwContext-本操作的设备关联符定义。DWORD dwAccessType-访问类型,为以下参数之一,INTERNET_OPEN_TYPE_PRECONFIG (default), INTERNET_OPEN_TYPE_DIRECT, 或 INTERNET_OPEN_TYPE_PROXY
LPCTSTR pstrProxyName-如访问类型为INTERNET_OPEN_TYPE_PROXY,则给该参数赋予协议名称。
LPCTSTR pstrProxyBypass-如访问类型为INTERNET_OPEN_TYPE_PROXY,则该参数为不通过协议服务器而直接链接的一系列地址。DWORD dwFlags-可为以下参数,INTERNET_FLAG_DONT_CACHE, INTERNET_FLAG_ASYNC, 和INTERNET_FLAG_OFFLINE.
dwAccessType值缺省时将使用系统注册簿定义的值。显然,程序允许使用者定义访问类型将比由程序内部直接定义要好。因此,要正确使用本程序,必需先在windows系统中定义好网络访问类型,步骤如下:1、双击桌面上“my computer"图标。
2、点击“contyol panel".
3、点击“internet ”。
4、在随后弹出的对话框中,选“connection"栏,然后填写网络连接属性。如果你是拨号上网,选中“dial”选择项,并填写相关属性。如果你是通过proxy服务器上网,选中“proxy”选项,点击“setting”按钮,设置proxy服务器地址和端口号。如果你是直接连入internet,应使所有的选项均为非选中状态。本程序在构造CInternetSession对象时使用缺省值,因此,构造函数将不带任何参数。如下所示:
CInternetSession session;
在构造对象session后,我们需写两行程序作一些输出,表示程序已开始工作。
m_out+="正在链接"+URL+"\r\n";
UpdateData(FALSE);接下来我们使用session对象的成员函数OpenURL()来打开一个URL资源。该函数返回一个文件的指针,文件类型为以下四种之一:
// 如果访问的是本地机器,函数返回一个CStudioFile类对象的指针。
ftp:// 如果访问的是一ftp地址,函数返回一个CInternetFile类对象的指针。
gopher:// 如果访问的是一gopher地址,函数返回一个CGopherFile类对象的指针。
http:// 如果访问的是一http地址,函数返回一个CHttpFile类对象的指针。本程序用于访问远程机器,因此,函数不会返回一个//类型的本地文件。而CGopherFile和CHttpFile均派生自CInternetFile,所以将该函数返回值赋给CInternetFile类的指针是安全的。当OpenURL()不能正常打开URL资源时,该函数将会抛出一个异常(exception),从而导致程序运行时错误。由于本程序用于探查未知的网址,该网址可能不提供相应服务或根本不存在,因此OpenURL()有时可能不会正常运行。为了避免程序异常终止,我们需使用try-catch结构来处理异常。本段程序代码如下:
CInternetFile* file=NULL;
try
{
file=(CInternetFile*)session.OpenURL(URL);
}
catch(CInternetException* pEx)
{
file=NULL;//如果发生运行时错误,给file赋空值,程序将继续运行
pEx->Delete();
}通过以上代码,程序将使用用户指定的地址来试图打开Http网址,如果失败,返回的文件为空,程序将继续运行,尝试用其它协议打开网址。随后,无论网址是否成功打开,我们都应作相应输出以提示用户。如果成功,我们用一个for循环读出返回文件的头20句并输出,如果失败,也要给出相应的提示。程序如下:
if(file) //判定链接是否成功
{
m_out+="已建立链接。\r\n";
CString line;
for(int i=0;i<20&&file->ReadString(line);i++)
{
m_out+=line+"\r\n";
}
file->Close();
delete file;
}
else
{
m_out+="本地址没有发现http主机\r\n";
}
m_out+="---------
上一个:从HTML语言到网上家园 第二章 构成网页的基本元素(5)
下一个:使用流加载和保存HTML内容&遍历html的信息存入一个ini文件&使用MSHTML分析HTML代码