WinInet开发Internet客户端应用指南

实现步骤

大家知道,每个Internet客户端
程序都伴随有一定的目的行为,如读文件、写文件、删除文件等等。客户端的程序要实现这些行为的先决条件是建立Internet连接。然后再根据不同的目的进行具体的操作。为了方便起见,下面这这些张表格针对不同的应用行为列出了所需要的具体操作。其中列出了一般的Internet URL (FTP、或者 HTTP)客户端行为要实现某个目标所必须使用的方法。这张表格的内容来自MSDN。我对部分我认为重要的地方做了补充。

(表一)一个典型的Internet客户端
程序的处理流程

目的 方法 结果
开始一个Internet session 创建 CInternetSession 对象 初始化WinInet,并连接服务器
读取或设置 InternetQuery 选项 (如超时或重试次数) 调用 CInternetSession::SetOption 不成功返回FALSE
建立回调函数监视session状态 调用CInternetSession::EnableStatusCallback
建立回调函数
CInternetSession::OnStatusCallback,重写OnStatusCallback,创建自己的回调例程
Internet服务器Intranet服务器或本地文件 调用 CInternetSession::OpenURL 解析并打开到指定服务器的连接,返回CStdioFile(如果你传递的OpenURL是本地文件名)或CInternetFile对象,通过存取这个对象,获得服务器文件的数据
文件 调用 CInternetFile::Read 用你提供的Buffer读指定的字节数
异常处理 在 CInternetException 类中处理 处理所有普通的 Internet 异常类型
结束 Internet session 处理 CInternetSession对象 自动清除打开的句柄的连接


(表二)典型的 FTP 客户端程序实现的一般步骤

目的 方法 结果
开始一个FTP会话,建立一个FTP连接 创建一个CInternetSession对象,调用CInternetSession::GetFtpConnection 初始化WinInet
并联接服务器
连接到一个FTP Server 用CInternetSession::GetFtpConnection 返回一个CFtpConnection对象
CD到 FTP 服务器的一个新目录 用CFtpConnection::SetCurrentDirectory CD到FTP服务器的一个
新目录
Find 第一个FTP目录中的文件 创建一个CFtpFileFind对象,调用CFtpFileFind::FindFile,OpenURL函数返回一个只读资源对象;调用CFtpFileFind::FindFile Find第一个文件,如果文件每找到返回FALSE
枚举所有可获得的资源,Find下一个FTP目录中的文件 Find下一个资源,调用CFtpFileFind::FindNextFile直到返回FALSE。 Find下一个文件
如果文件没找到返回FALSE
打开FindFile或FindNextFile找到的文件(用于读写) 调用CFtpConnection::OpenFile,参数为FindFile或FindNextFile返回的文件名 ,创建并打开一个CInternetFile对象 打开FindFile或FindNextFile找到的文件(用于读写),返回一个CInternetFile对象
读写文件 以读方式打开FTP文件,用CInternetFile::Read 使用你指定的缓冲读
指定的字节数
写FTP文件 以写方式打开FTP文件,调用CInternetFile::Write,重写CInternetSession::OnStatusCallback 使用你指定的缓冲写
指定的字节数
改变客户端在服务器上的目录 调用CFtpConnection::SetCurrentDirectory 进入新的目录
获取客户端在服务器上的当前目录 调用CFtpConnection::GetCurrentDirectory 获取目录信息
异常处理 用CInternetException类 处理所有普通的Internet异常类型
结束FTP session 处理CInternetSession对象 自动清除打开的句柄的连接


(表三)显示了一个典型的删除文件的FTP客户端应用要实现的一般步骤:

目的 方法 结果
开始一个FTP session 创建一个CInternetSession对象 初始化WinInet
并联接服务器
连接到一个FTP Server 用CInternetSession::GetFtpConnection 返回一个CFtpConnection对象
检查FTP目录是否正确 用CFtpConnection::GetCurrentDirectory或CFtpConnection::GetCurrentDirectoryAsURL 返回目录名字
服务器目录或返回目录的URL
CD(改变目录)到 FTP 服务器的一个新目录 用CFtpConnection::SetCurrentDirectory CD到FTP服务器的一个
新目录
Find 第一个FTP目录中的文件 用CFtpFileFind::FindFile Find第一个文件,如果文件每找到返回FALSE
Find 下一个FTP目录中的文件 用CFtpFileFind::FindNextFile Find下一个文件
如果文件没找到返回FALSE
删除FindFile或FindNextFile找到的文件 用CFtpConnection::Remove用FindFile或FindNextFile返回的文件 删除FindFile或FindNextFile
找到的文件
异常处理 用CInternetException类 处理所有普通的Internet异常类型
结束FTP session 处理CInternetSession对象 自动清除打开的句柄的连接


(表四)显示了实现一个典型的 HTTP 客户端应用程序的一般步骤:

目的 方法 结果
开始HTTP会话,建立HTTP连接 创建 CInternetSession对象,调用CInternetSession::GetHttpConnection
创建CHttpConnection对象
初始化WinInet并联接服务器,返回一个CHttpConnection对象
创建一个 HTTP 请求 调用CHttpConnection::OpenRequest
创建一个CHttpFile对象;
返回一个CHttpFile对象
发送一个HTTP 请求 用CHttpFile::AddRequestHeaders 并且用CHttpFile::SendRequest Find一个文件
如果文件没找到返回FALSE
文件 调用CInternetFile::Read 使用你提供的缓冲读指定的字节
获取HTTP请求信息 调用CHttpFile::QueryInfo 服务器获取HTTP请求头信息
异常处理 利用CInternetException类 处理所有普通的Internet异常类型
结束 HTTP 会话 处理CInternetSession对象 自动清除打开的句柄的连接

由于时间关系,我没有写本文的例子代码。不过MSDN里有两个简单的例子可以参考,一个是FTPTREE,另一个是TEAR。此外,也可以用“WinInet”作为关键字在google里搜一下也能找到一些使用MFC WinInet的技术信息。(完)

9月3日

VC Post HTTP

vc中如何用post方法提交表单 在vc中如何用post方法提交表单!

我这里有一段程序,用来在一个对话框里显示出一次http request的原始信息,不过使用Inet API做的,希望能有帮助。

void CHTTPRequestDlg::OnButtonRequest()
{
UpdateData(TRUE);
HINTERNET hInternet = InternetOpen("Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0)", INTERNET_OPEN_TYPE_DIRECT,
NULL, NULL, NULL);
HINTERNET hSession = InternetConnect(hInternet, m_strHost,
m_nPort, "username", "password",
INTERNET_SERVICE_HTTP, 0, 0);
char* szAccept[] = {"*/*", NULL};
CString strVerb;
m_comboVerb.GetWindowText(strVerb);
HINTERNET hRequest = HttpOpenRequest(hSession, strVerb, m_strObject, NULL, NULL, (LPCSTR*)szAccept, 0, 0);
struct
{
char* Language;
char* Encoding;
char* ContentType;
}Headers = {"Accept-Language: zh-cn\r\n",
"Accept-Encoding: gzip, deflate\r\n",
"Content-Type: application/x-www-form-urlencoded\r\n"};

if(m_bLanguage)
HttpAddRequestHeaders(hRequest, Headers.Language, -1, HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);
if(m_bEncoding)
HttpAddRequestHeaders(hRequest, Headers.Encoding, -1, HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);
if(m_bContentType)
HttpAddRequestHeaders(hRequest, Headers.ContentType, -1, HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);
LPCSTR lpAddHeader = NULL, lpContent = NULL;
if(m_strHeaders.GetLength())
{
if(m_strHeaders.Right(2) != "\r\n")
m_strHeaders += "\r\n";
lpAddHeader = (LPCSTR)m_strHeaders;
}
if(m_strContent.GetLength() && (strVerb == "POST" || strVerb == "PUT"))
lpContent = (LPCSTR)m_strContent;
HttpSendRequest(hRequest, lpAddHeader, -1, (LPVOID)lpContent, m_strContent.GetLength());

m_editContentGot.SetSel(0, -1);
m_editContentGot.ReplaceSel("");


LPSTR lpszData; // buffer for the data
DWORD dwSize; // size of the data available
DWORD dwDownloaded; // size of the downloaded data

// Set the cursor to an hourglass.
SetCursor(LoadCursor(NULL,IDC_WAIT));

// This loop handles reading the data.
while(1)
{
// The call to InternetQueryDataAvailable determines the amount of
// data available to download.
if (!InternetQueryDataAvailable(hRequest,&dwSize,0,0))
{
SetCursor(LoadCursor(NULL,IDC_ARROW));
break;
}
else
{
// Allocates a buffer of the size returned by InternetQueryDataAvailable
lpszData = new char[dwSize+1];

// Reads the data from the HINTERNET handle.
if(!InternetReadFile(hRequest,(LPVOID)lpszData,dwSize,&dwDownloaded))
{
delete[] lpszData;
break;
}
else
{
// Adds a null terminator to the end of the data buffer
lpszData[dwDownloaded]='\0';

int nLen = m_editContentGot.GetWindowTextLength();
m_editContentGot.SetSel(nLen-1, nLen-1);
m_editContentGot.ReplaceSel(lpszData);

// Delete the two buffers
delete[] lpszData;

// Check the size of the remaining data. If it is zero, break.
if (dwDownloaded == 0)
break;
}
}
}

// Close the HINTERNET handle
InternetCloseHandle(hRequest);
InternetCloseHandle(hSession);
InternetCloseHandle(hInternet);

// Set the cursor back to an arrow
SetCursor(LoadCursor(NULL,IDC_ARROW));



使用MFC示例如下:
首先设置m_strRequest请求字符串 eg."name=aaa&pass=bbb";
m_strServerName 服务器名称或者IP eg."www.yahoo.com"
m_strObjectName 请求文件位置 eg. "pub/aaa.asp"
请求的结果存放在m_strHtml中
func(){
CInternetSession m_InetSession("session");
CHttpConnection* pServer = NULL;
CHttpFile* pFile = NULL;
try{
INTERNET_PORT nPort;
nPort=80;
pServer = m_InetSession.GetHttpConnection(m_strServerName, nPort);
pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST,
m_strObjectName);
char szHeaders[100];
strcpy(szHeaders,"Accept: text*/*\r\nContent-Type: application/x-www-form-urlencoded");
pFile->AddRequestHeaders(szHeaders);


pFile->SendRequestEx(m_strRequest.GetLength());
pFile->WriteString(m_strRequest); //重要-->m_Request 中有"name=aaa&name2=BBB&..."
pFile->EndRequest();
DWORD dwRet;
pFile->QueryInfoStatusCode(dwRet);
CString str;

m_Mutex.Lock();
m_strHtml="";
char szBuff[1024];
if (dwRet == HTTP_STATUS_OK){
UINT nRead;
while ((nRead = pFile->Read(szBuff,1023))>0)
{
m_strHtml+=CString(szBuff,nRead);
}
}
m_Mutex.Unlock();

delete pFile;
delete pServer;
}
catch (CInternetException* e){
CString s;
s.Format("Internet Exception\r\nm_dwError%u,m_dwContextError%u",e->m_dwError,e->m_dwContext);
AfxMessageBox(s);
//catch errors from WinInet
}
}

你可能感兴趣的:(session,FTP服务器,服务器,null,delete,internet)