用WinInet开发Internet客户端应用指南

lwsjmr 2011-05-26 12:45:39
用WinInet开发Internet客户端应用指南(一)


编译/NorthTibet


一、概述

一个Internet客户端程序的目的是通过Internet协议如:HTTP、FTP等来存取网络数据源(服务器)的信息。客户端程序可以访问服务器获得象天气预报,股票价格、重要新闻数据,甚至是与服务器交换信息。Internet客户端程序可以通过外部网络(Internet)或内部网络(一般为Intranet)访问服务器。
为了开发Internet客户端程序。MFC类库提供了专门的 Win32 Internet 扩展接口,也就是WinInet。MFC将WinInet封装在一个标准的、易于使用的类集合中。在编写WinInet客户端程序时,你既可以直接调用Win32函数,也可以使用WinInet类库。
Win32 Internet 扩展提供了对普通Internet协议的访问,这些协议包括:HTTP、FTP和Gopher。Gopher已经渐渐淡出。借助于WinInet编程接口,开发人员不必去了解Winsock、TCP/IP和特定Internet协议的细节就可以编写出高水平的Internet客户端程序。WinInet为所有几种协议(HTTP、FTP和Gopher)提供了统一的函数集,也就是Win32 API接口。利用这些统一的函数集,大大简化了针对HTTP、FTP等协议的编程,从而轻松地将Internet集成到自己的应用程序中。底层协议的转换(如从FTP到HTTP)只要对源代码稍作修改就可以完成。
在Visual C++工程中提供有两种方式来使用WinInet。一种是直接调用Win32 Internet函数,另一种是使用WinInet类库。
MFC对WinInet的封装是通过提供三个由CStdioFile派生类实现的。这三个派生类是:CInternetFile、 CHttpFile 和 CGopherFile。由于Gopher协议已经很少使用,所以本文将不再对CGopherFile进行讨论。对开发人员来说,不管你以前是否用过CStdioFile,WinInet都是很好理解并且易于使用的。它使得存取Internet数据易如反掌,使得Internet数据和本地数据的处理一致透明,数据的存储位置已经不再重要。

MFC WinInet 类有如下优点:
缓冲器输入输出
数据的类型安全处理
许多函数的参数都是缺省值
对普通的Internet错误进行异常处理
自动清除打开的句柄和连接
使用 WinInet 提供的API函数,你可以:
通过HTTP协议下载HTML页,HTTP协议是专门用于在服务器和客户浏览器之间传输HTML页。
发送FTP请求上传或下载文件以及获取服务器的目录信息。通过匿名登陆下载文件便是FTP的典型应用。
其它基于HTTP、FTP协议的应用。
使用 WinInet 的一般流程为:



图一

下表描述了一个Internet客户端程序实现的一般步骤:
(表一)
实现 方法
建立一个连接 创建CInternetSession对象,它是WinInet Internet客户应用的前提条件
打开一个URL 建立一个连接,调用CInternetSession::OpenURL
函数,返回一个只读资源对象
读取 URL 数据 打开一个URL,调用CInternetSession::QueryOption
查询 Internet 选项设置 建立一个连接,调用CInternetFile::Read
设置一个Internet选项 建立一个连接,调用CInternetSession::SetOption
设置一个用状态信息调用的函数 建立一个连接,调用CInternetSession::EnableStatusCallback
重写CInternetSession::OnStatusCallback函数
关闭连接 用CInternetSession对象方法,清除打开的连接

为了创建Internet客户端程序,MFC提供了如下的C++类和全程函数:

C++类

CInternetSession (父类 CObject)
CInternetConnection (父类 CObject)
CFtpConnection
CGopherConnection
CHttpConnection
CInternetFile(父类 CStdioFile)
CGopherFile
CHttpFile
CFileFind(父类 CObject)
CFtpFileFind
CGopherFileFind
CGopherLocator(父类 CObject)
CInternetException(父类 CException)
全程函数: AfxParseURL
AfxGetInternetHandleType
AfxThrowInternetException
这些类和全程函数除CFileFind在AFX.H里声明之外,其余都在AFXINET.H文件里声明。它们对HTTP、FTP和Gopher等协议进行了高度抽象,形成了一套高级API函数。 利用这些API可以快速直接地开发Internet应用。例如,连接到FTP服务器一般需要几个步骤,而且需要做一些底层处理。但使用上述的MFC类提供的API,只需要对CInternetSession::GetFTPConnection进行一次调用,便可以轻松建立连接。
大家知道,每一个Internet应用其数据交换都是建立在Internet会话(Session)的基础之上的,MFC是通过CInternetSession类对象来实现Internet会话的。用这个类不仅可以创建会话,而且可以创建几个并发的Internet会话。
为了与服务器进行通讯,除了要创建CInternetSession对象之外,还必须创建CInternetConnection对象,针对不同的协议,CInternetConnection对象有三种类型:
CInternetSession::GetFtpConnection
CInternetSession::GetHttpConnection
CInternetSession::GetGopherConnection
这些函数调用并不会读写服务器上的文件。如果你想要读写数据,必须要打开文件才能操作。其处理流程应该是这样的:
首先创建 CInternetSession 对象实例
如果创建的Session要读写文件,则必须创建 CInternetFile 对象实例(或者是它的子类CHttpFile、CGopherFile 对象实例)。其实,读取数据最容易的方式是调用 CInternetSession::OpenURL函数。 这个函数解析你提供的统一资源定位符(URL),然后打开与URL指定的服务器连接,同时返回一个只读的CInternetFile对象。CInternetSession::OpenURL不针对特定的协议类型——不管是FTP还是HTTP都可以调用,它甚至可以处理本地文件,此时返回的是CStdioFile,而不是CInternetFile。
如果创建的Session不读写文件,而是要实现其它的任务,如删除某个FTP目录下的文件等,则你不需要创建CInternetFile实例。
创建CInternetFile对象的方法有两种:
如果用CInternetSession::OpenURL建立与服务器的连接,调用返回CStdioFile。
如果用CInternetSession::GetFtpConnection、GetGopherConnection或者CHttpConnection::OpenRequest建立与服务器的连接,你必须调用相应的CFtpConnection::OpenFile、CGopherConnection::OpenFile或者CHttpConnection::OpenRequest,返回的内容也与CInternetFile、CGopherFile或者CHttpFile对应。
综上所述,实现Internet客户端应用的步骤因协议而异。要看你是创建基于OpenURL的一般Internet客户端应用,还是使用GetXXXConnection函数之一针对特定协议的Internet客户端应用。
在后继文章中我们将进一步讨论用WinInet实现Internet客户端应用程序的具体步骤和细节。(待续)



...全文
2417 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
lwsjmr 2011-05-26
  • 打赏
  • 举报
回复
五: 代码如下:
// crt_assert.c
// compile with: /c
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>


#include <iostream>

#include "winsock2.h"
#include <string>
#include <Wininet.h>
#include <windows.h>
#include <fstream> //要使用文件输入输出流必须的头文件
using namespace std;
#define __HTTP_VERB_GET "GET"
#define __HTTP_VERB_POST "POST"
#define __HTTP_ACCEPT_TYPE "*/*"
#define __HTTP_ACCEPT "Accept: */*\r\n"
#define __SIZE_HTTP_BUFFER 100000
#define __SIZE_HTTP_RESPONSE_BUFFER 100000
#define __SIZE_HTTP_HEAD_LINE 2048

void CALLBACK InternetStatusCallback(

HINTERNET hInternet,
DWORD dwContext,
DWORD dwInternetStatus,
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength);
HANDLE hEvent[3];

HINTERNET hFile;
HINTERNET hNet;
HINTERNET hSession,hConnect,hRequest;
int WaitExitEvent()
{
//return 1;
DWORD dwRet = ::WaitForMultipleObjects(3, hEvent, FALSE, 30000);//INFINITE);
int x=-1;
switch (dwRet)
{
//句柄被创建事件或者读数据请求成功完成事件
case WAIT_OBJECT_0:
x=0;
cout<<"WAIT_OBJECT_0"<<endl;
//句柄被关闭事件
break;
case WAIT_OBJECT_0+1:
x=1;
cout<<"WAIT_OBJECT_1"<<endl;
//用户要求终止子线程事件或者发生错误事件
break;
case WAIT_OBJECT_0+2:
x=2;
cout<<"WAIT_OBJECT_2"<<endl;

break;
default:
cout<<"WaitForMultipleObjects time out"<<endl;
return -1;

}
return x;
}

// 支持代理设置, 是否异步设置; 采用事件驱动
void WinINet3(bool setProxy, bool ASYNC)
{
hSession=NULL;
hConnect=NULL;
hRequest=NULL;
for (int i = 0; i < 3; i++)
{
hEvent[i] = CreateEvent(
NULL, // default security attributes
FALSE, // auto-reset event object
FALSE, // initial state is nonsignaled
NULL); // unnamed object

if (hEvent[i] == NULL)
{
printf("CreateEvent error: %d\n", GetLastError() );
ExitProcess(0);
}
}
char *url = "http://down.360safe.com/setup.exe";
char *pip = "down.360safe.com";
char *paim = "/setup.exe";



// step 1
if(ASYNC) cout<<"异步模式"<<endl;
// setProxy =false;
if(setProxy)
{
cout<<"代理模式"<<endl;
if(ASYNC)
hSession = InternetOpen("name",
INTERNET_OPEN_TYPE_DIRECT,//|INTERNET_OPEN_TYPE_PROXY,// INTERNET_OPEN_TYPE_PROXY,
NULL,NULL,INTERNET_FLAG_ASYNC); // 异步
else
hSession = InternetOpen("name",INTERNET_OPEN_TYPE_PROXY,NULL,NULL,0); // 同步
}
else
{
if(ASYNC)
hSession = InternetOpen("name",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,INTERNET_FLAG_ASYNC); // 异步
else
hSession = InternetOpen("name",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0); // 同步
}
if(!hSession){
DWORD er = ::GetLastError();
cout<<"InternetOpen error"<<endl;//, "Err", MB_OK);
return;
}
if(ASYNC)
{
//Sleep(500);
INTERNET_STATUS_CALLBACK res = ::InternetSetStatusCallback(hSession,InternetStatusCallback);
if(res == INTERNET_INVALID_STATUS_CALLBACK)
{
cout<<"InternetSetStatusCallback failed, so return "<<endl;
return ;
}
else
{
cout<<"InternetSetStatusCallback succeed, so go on "<<endl;

}
//Sleep(500);
}

char strProxyList[MAX_PATH], strUsername[64], strPassword[64];
strcpy(strProxyList, "SOCKS=58.56.87.2:1080"); // 写上socks怎么就无效了呢???SOCKS5=172.18.132.27:1080
strcpy(strUsername, "user01");
strcpy(strPassword, "baidu");
INTERNET_PROXY_INFO proxy;
proxy.dwAccessType = INTERNET_OPEN_TYPE_PROXY;
proxy.lpszProxy = strProxyList;
proxy.lpszProxyBypass = NULL;
if( setProxy &&!InternetSetOption(hSession,INTERNET_OPTION_PROXY ,&proxy,sizeof(INTERNET_PROXY_INFO)))
{
cout<<"InternetSetOption failed"<<endl;
return ;
}

// step 2
//如果明确知道需要认证,第4,5个参数可以输入用户名,密码"administrator","password"
//第2,3个参数为目标主机IP、端口号(不是代理服务器的参数)
hConnect = InternetConnect(hSession,pip,INTERNET_DEFAULT_HTTP_PORT,NULL,NULL,INTERNET_SERVICE_HTTP,INTERNET_FLAG_RELOAD,0);
if(!ASYNC &&!hConnect){
cout<<"同步,InternetConnect error"<<endl;//, "Err", MB_OK);
return;
}
if( ASYNC&& hConnect== NULL)// 异步 需要等待 竟然直接创建好了
{
int er = GetLastError();
DWORD dwError = ::GetLastError();
if (dwError != ERROR_IO_PENDING)
{
cout<<"CHttpDownload::OpenInternetConnection| 连接失败" <<endl;
return ;
}
else //
{
cout<<"hConnect == NULL, so run WaitExitEvent"<<endl;
WaitExitEvent(); // 等待成功创建 // 这里应该等待 这里应该显示一次呀
::ResetEvent(hEvent[0]);
::ResetEvent(hEvent[1]);
::ResetEvent(hEvent[2]);
}
}
cout<<"step 2 :InternetConnect secced"<<endl;

// ::InternetSetStatusCallback(hConnect,InternetStatusCallback);

// step 3!!!
char szHead[] = "Accept: */*\r\n\r\n";
char **p = new char*[2];*p = szHead;*(p+1) = NULL;

//hRequest = HttpOpenRequest(hConnect,"GET","download/BaiduHi_1.0_Beta2.exe",NULL,NULL,/*(const char **)p*/NULL,0/*INTERNET_FLAG_NO_COOKIES|INTERNET_FLAG_RELOAD*/,0); // no request;
CONST TCHAR *szAcceptType=__HTTP_ACCEPT_TYPE;
hRequest = ::HttpOpenRequest(hConnect,
"GET",
paim,
HTTP_VERSION,
"",
&szAcceptType,
INTERNET_FLAG_RELOAD|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_NO_CACHE_WRITE,
0);

//::HttpAddRequestHeaders( hRequest, __HTTP_ACCEPT, strlen(__HTTP_ACCEPT), HTTP_ADDREQ_FLAG_REPLACE);
/*_hHTTPRequest=::HttpOpenRequest( _hHTTPConnection,
__HTTP_VERB_GET, // HTTP Verb
szURI, // Object Name
HTTP_VERSION, // Version
"", // Reference
&szAcceptType, // Accept Type
INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_CACHE_WRITE,
0); // context call-back point
*/
if (!ASYNC&& !hRequest){
cout<<"同步,HttpOpenRequest error"<<endl;//, "Err", MB_OK);
return;
}
if( ASYNC&& hRequest== NULL)// 异步 需要等待
{
int er = GetLastError();
DWORD dwError = ::GetLastError();
if (dwError != ERROR_IO_PENDING)
{
cout<<"CHttpDownload::OpenInternetConnection| 连接失败" <<endl;
return ;
}
else //
{
cout<<"hRequest == NULL, so run WaitExitEvent"<<endl;
WaitExitEvent(); // 等待成功创建
::ResetEvent(hEvent[0]);
::ResetEvent(hEvent[1]);
::ResetEvent(hEvent[2]);
}
}
//Sleep(10000);
cout << "step 3 : HttpOpenRequest success"<<endl;
//::InternetSetStatusCallback(hRequest,InternetStatusCallback);
//////////////////////////////////////////////
lwsjmr 2011-05-26
  • 打赏
  • 举报
回复
一 WinINet是干什么的?
二 如果完成一个基本的WinINet操作流程
三 如何异步完成,异步操作的好处。
四 unicode以及mutilbyte
五 代码样例

一 WinINet是微软开发的一个库,可以完成http ftp客户端的工作。让程序员从复杂的协议中节省大量体力。

二 我会用了http, ftp类似。用WinINet完成一个http下载需要以下步骤 。 下面这个是同步操作(也就是一步步操作,每个函数执行完才会返回一个结果的意思)

1 InternetOpen Initializes an application's use of the WinINet functions.
需要的话 InternetSetOption 设置代理服务器地址以及端口。
http: ip:port 或者 http=http://ip:port
socks:SOCKS=ip:port
2 InternetConnect 关联目标地址或者域名以及服务ip

3 HttpOpenRequest 关联要下载的内容名字
InternetSetOption 设置用户名密码

4 HttpSendRequest 这步就是用HttpOpenRequest 的返回值(已经关联了上面的所有信息)发送出去,第一次用了网络。向目标服务器或者代理服务器。

5 HttpQueryInfo
该函数查询返回值,不参与网络操作。可以查询服务器的返回信息,比如目标文件的大小,该文件是否存在,代理服务返回了要求用户名,密码等等(这几个最常用),还有很多信息。

6 InternetReadFile
很普通的读函数,就是下载文件。不知道是否和底层网络同步,底层会不会提前下载呢?

7 InternetCloseHandle 释放资源

三 异步操作,比较复杂的。 为什么需要异步操作呢? 因为涉及到网络操作,某些函数在操作中可能需要时间,如果一直不返回(比如1秒)时,这时主线程要结束程序,岂不就出现意想不到的结果了,但是如果每个函数都能够瞬间返回,然后通过WaitForMultipleObjects或者WaitForSingleObject等待结果的出现(此时就不会操作那个消耗1秒的函数了,而这个1秒函数正是要用到系统资源HINTERNET的)。

异步操作的目的上如,原理呢? 其实原理就是注册一个函数,在这里叫InternetStatusCallback,因为微软写得底层代码要用到,所以必须格式统一。一旦有结果来了就通过事件通知我们,WaitForSingleObject函数就可以走了。比如等到了HINTERNET创建或者命令发送成功等结果。然后我们就可以第一时间安全的使用了。
API 函数如果名字最后可以带EX,那么带ex的就是异步操作的。

四 一定要注意,凡是有unicode和mutilbyte函数的一定要统一,最好都用mutilbyte的。


lwsjmr 2011-05-26
  • 打赏
  • 举报
回复
Winsock是Windows应用程序间TCP/IP通信的标准。以此为基础的Visual C++4.2以上版本提供的API—WinInet,使Internet程序开发变得快捷而方便。本文研究探讨了如何利用WinInet类实现TCP/IP通信。
  关键词:Internet编程 Winsock类 TCP/IP FTP HTTP Gopher

1 基于Windows操作系统的Internet编程
  Internet早期的站点是UNIX机器,他们实现TCP/IP通信的标准是Berkeley sockets协定。
  随着Windows操作系统的形成与发展,借鉴Berkeley sockets的思想,创建了在Windows应用程序之间实现TCP/IP通信的标准——Windows Sockets(Winsock)标准。
  在此基础之上,又开发了一些便于程序员按照客户/服务者(Client/Server)模式进行Internet编程的API。因此,程序员可根据不同需要采用不同的方法实现TCP/IP通信:直接使用Winsock;使用消息API(Message API);使用Internet服务者API(ISAPI);利用Visual C++4.2以上版本提供的Internet类及函数——WinInet。其中,Winsock环境(WINSOCK.DLL、WSOCK32等)的接口,它保证了在不同的Windows环境(如Windows95或Windows NT)下,不论动态库的名称与实现socket功能的机制如何,socket接口是相同的。Winsock不仅可实现TCP/IP通信,还可支持其它协议,如IPX/SPX。MAPI服务提供利用用户已安装的客户端服务软件发送传真、声音邮件、电子邮件等信息的接口(API)。ISPAI用于增强、扩展HTTP服务器功能,它的开发者制造extensions与filters:extensions是可由用户从Web页面上调用的动态库,它类似于CGI应用程序;filters是由服务器启动的动态库,用于监视或改变出、入服务器的数据。WinInet提供了HTTP、FTP、Gopher等应用层协议的客户端接口。
  WinInet使Internet程序开发变得快捷而方便。本文将对WinInet以及如何利用WinInet开发Internet通信程序进行介绍和探讨。
2 WinInet
2.1 什么是WinInet
  WinInet是指由Microsoft Win32提供的Internet函数,在WININET.DLL动态库中所包含的这些函数使得程序员能方便地使用HTTP、FTP和gopher访问Internet,再稍加变通后还能进行Finger查询和Whois查询。VC 4.2以上版本的MFC则提供了WinInet类,这些类屏蔽了WinSock和TCP/IP协议,程序员只须调用这些类的方法,而不用了解协议的具体内容就能编制客户端程序访问HTTP、FTP、gopher等站点。
2.2 WinInet类及其功能
  MFC共提供了13个WinInet类,它们实现了一系列Internet访问功能。
  (1)CInternetSession:创建1个或多个Internet通道。
  (2)CInternetConnection:与子类(ChttpConnection、CftpConnection、CGopherConnection)管理应用程序与Internet服务器(Http服务器、FTP服务器、gopher服务器)建立的连接。
  (3)CInternetFile:与子类(CHttpFile、CGopherFile)提供了访问远程服务器(Http服务器、gopher服务器)文件系统的方法。
  (4)CFileFind:与子类(CftpFileFind、CgopherFileFind)完成在本地及远程Internet站点(FTP服务器、 gopher服务器)查找文件的功能。
  (5)CGopherLocator:从gopher站点获取gopher位标(locator),并提供给CgopherFileFind用来定位。
  (6)CInternetException:描述与Internet操作有关的例外情况。
3 用WinInet编制Internet客户端程序
  Internet客户端应用程序指基于Internet协议(如gopher、FTP、HTTP等)从网络数据资源(服务器)获取信息的程序。程序员可以直接调用Win32函数或采用MFC的WinInet类编写WinInet客户端应用程序。
  作者在编制Internet客户端程序的过程中,用WinInet类完成了HTTP查询、FTP查询、gopher查询、Finger查询、Whois查询等功能模块的实现。查询的主要功能是设法与服务器建立连接,然后从服务器直接接受回应信息或获取对服务器相关文件系统的控制句柄。下面分别阐述不同协议查询方法的实现。
  WinInet类的声明在头文件"afxinet.h"中,在使用到WinInet类的应用程序中要有语句:
  #include<afxinet.h>
3.1 访问WWW服务器
  做一个HTTP连接,最简单的方法是创建CInternetSession对象,以某一有效HTTP站点URL为参数调用函数OpenURL(),它返回CInternetFile文件句柄,其内容为由此URL定位的web页面信息,可以像处理本地文件一样对其进行读、写、搜索等操作,获取必要的信息。有关程序代码如下:
  CInternetSession session;
  CInternetFile*file=NULL;
  try {
   file=(CInternetFile*)session.OpenURL(URL); }
  catch(CInternetException*pEx){
   file=NULL;
   pEx->Delete(); }
  if(file){
    //根据需要对文件读、写、搜索……;}
  其中try-catch语句捕捉非法URL连接而引发的CInternetException类错误,正常处理代码放入try{…}中,异常处理代码放在catch(){…}中。
  访问WWW站点,还可以使用ChttpConnection类。具体方法是,以http服务器域名及其执行http协议端口的端口号(缺省80)为参数,调用CinternetSession::GetHttpConnection()函数建立与某站点的连接,再用CHttpConnection::SendRequest函数向HTTP服务器发送服务请求,返回值为包含应答信息的CHttpFile类型的文件句柄。

3.2 访问FTP站点
  首先调用函数CInternetSession::GetFtpConnetion()建立FTP连接,所需要的参数依次为:FTP站点域名、用户名、用户口令、ftp服务端口号(缺省值为21)、访问模式(被动或主动),其中用户名若为空,则表明是请求匿名FTP服务,用户口令为用户的email地址。通过此连接用CftpConnection类的方法操作远程FTP服务器的文件系统,如用SetCurrentDirectory(GetCurrentDirectory)设置(获取)此连接的当前FTP目录,用RemoveDirectory(CreateDirectory)删除(创建)目录,用Rename、Remove、PutFile、GetFile及OpenFile等对文件进行更名、删除、移入、取出及打开等操作,最后必须用Close方法关闭与FTP服务器的连接。因此,可用MFC来编制提供图形界面的FTP客户端应用程序:(1)用MFC提供的各种控制器(如static text、edit box、Button、List Box、List control、Tree control等)编辑对话框界面,提供良好的命令输入及信息输出用户界面;(2)用MFC ClassWizard向相关类中加入响应用户命令操作的消息映射宏及处理函数;(3)建立FTP连接,并在相应的消息映射函数中加入程序代码,实现对FTP站点文件系统的操作,并将结果信息显示给用户。


建立FTP连接及远程文件操作的关键代码:
  CInternetSession session(“My FTP Session”);
  CFtpConnection* pConn=NULL;
  pConn=session.GetFtpConnection(lpSN,lpUN,lpPW,nP);
  //例:lpSN=“ftp.whnet.edu.cn”,lpUN=lpPW=“”,np=21,
  //对该站点匿名ftp访问;
  ……
  pConn->GetFile(pRF,pLF);
  //pRF——从FTP站点取回的文件名,
  //pLF——本地系统创建的文件名
  pConn->GetCurrentDirectory(strCD);
  //strCD 为Cstring对象的指针
  ……
  pConn->Close();  session.Close();
3.3 访问Gopher站点
  首先用CInternetSession::GetGopherConnection()函数与某合法Gopher站点建立连接,参数依次为Gopher服务器名、用户名、用户口令、gopher协议端口号(确省值为70),返回值为控制此连接的CGopherConnection对象的指针。
  CGopherConnection类的成员函数CreateLocator()用于创建CGopherLocator对象,它的3个参数依次为目录或文件名、查找关键字、类型标志位,返回值是gopher服务器某一文件或目录的定位器(locator),应用程序将此定位器看作不透明的记号,用于从gopher服务器检索信息。每个gopher定位器都有特定的属性来确定已查找到的文件或服务器的类型,CGopherLocator类的成员函数GetLocatorType()可获取定位器的属性。
  应用程序一般用gopher定位器,为参数调用CGopherFileFind类的成员函数FindFile()来查找一gopher文件。文件名可作为函数的第2个参数,返回一CGopherFile文件句柄,利用此句柄可读、写文件,获取所需信息;接下来还可调用CGopherFileFind类的另一成员函数FindNextFile(),继续查找同名文件。其中CGopherFileFind对象的创建要以此gopher连接作参数。
  查找gopher文件,还可直接使用CGopherConnection类的成员函数OpenFile(),它也需要gopher定位器作参数,返回CGopherFile文件句柄。
  建立gopher连接及查找相关文件的关键代码如下:
  CInternetSession session; CGopherConnection* con=NULL;
  CGopherFile* pgF=NULL;
  con=session.GetGopherConnection(host);
  //host是gopher服务器域名
  CGopherFileFind* pF=new CGopherFileFind(con);
  CGopherLocator lc=con->CreateLocator(NULL,NULL,
GOPHERTYPEDIRECTORY);
  pgF=pF->FindFile(lc,pFN);//pFN为文件名字符串
  ……
3.4 用Gopher传送Finger查询
  Finger是一种查询某一站点的所有在线用户或某一指定用户状况的古老Internet协议。在MFC类及API函数名中均不含有finger这一单词,但可以通过指定协议端口的方式,用与gopher查询相关的WinIntet类或API函数实现finger查询。
  Internet信息交互均有特定主机和端口与之对应,域名(或IP地址)确定主机,端口(port)确定进程。著名的协议采用标准端口号。例如,当应用程序用远程主机域名、端口号70、gopher类型(0)、文件名字符串等4个参数创建gopher定位器(locator)时,gopher客户端将此字符串发送给用该远程主机的端口70,远程主机上gopher服务器监听端口70,在收到查询字符串后按gopher协议规定回应信息。Finger协议的标准端口是79,远程主机上的Finger服务器,监听此端口并发送Finger应答来响应由客户端发来的字符串。Finger协议规定:若字符串是“\r\n”,回应信息是主机上所有在线用户的相关信息列表;若字符串是“用户名+\r\n”,回应信息是该用户的相关信息。
  因此,进行Finger查询,可以调用成员函数CinternetSession::GetGopherConnection(),以运行Finger服务器程序的远程主机名及端口79作参数,建立Finger连接。在调用CGopherConnection的成员函数CreateLocator()创建定位器时,以客户端发送的Finger查询字符串作为参数II(查找关键字),即可向Finger站点发出查询信息,Finger站点的应答信息则置于CGopherFile文件中带回。
  建立Finger连接并进行Finger查询的关键代码如下:
  CInternetSession session; CGopherConnection*con=NULL;
  con=session.GetGopherConnection(hostName,NULL,NULL,79);
  CGopherLocator lc=con->CreateLocator(NULL,qstr,GOPHERTYPETEXTFILE);
  //qstr是“\r\n"或“用户名+\r\n"
  CGopherFile* file=con->OpenFile(lc);
  …  //读文件

3.5 用Gopher传送Whois查询
  Whois协议也不被WinInet类直接支持。类似于Finger,Whois对发到其端口的字符串作出响应,Whois的标准端口是43。Whois服务通常由Internet上的DNS服务系统提供。在创建定位器时,以待查找的主机名作为查找关键字,即可由返回的CGopherFile文件带回查询结果。
  在下面的Whois查询范例中,“rs.internic.net"是提供Whois服务的主机的域名,“www.microsoft.com"是被查询主机的域名。
  CInternetSession se; CGopherConnection* con=NULL;
  con=se.GetGopherConnection(“rs.internic.net",NULL,
NULL,43);
  CGopherLocator lc=con->CreateLocator(NULL,
“www.microsoft.com",0);
  CGopherFile* file=con->OpenFile(lc);
  …//读文件;
  上述利用WinInet类编制Internet客户端程序的方法,可以方便地访问HTTP、FTP、Gopher、Finger、Whois等站点

Eleven 2011-05-26
  • 打赏
  • 举报
回复
分享???

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧