HTTP 1.1是一个基于文本的互联网实体信息交互主流协议,协议的分析已经在《HTTP协议格式分析》文中详细介绍。
HTTP 1.1协议中的请求类型可以是下面的一种:
1. OPTION:返回请求者和相应者之间可以使用的通信选项,主要用来检测服务器处理能力;
2. GET:获得以URL标示的文件内容或者程序执行结果。服务器根据文件名后缀判断服务内容,比如该URL是静态文本还是一个程序;
3. HEAD:除了不返回响应的信息本体以外,得到的是跟GET一样的信息。一般用来测试链接的有效性、可达性和近期修改;
4. POST:把消息本体中的消息发送到一个URL或者其他类似的服务器端定义行为。通常用来提交一个HTML表单或者一些数据操作活动;
5. PUT:把消息本体中的消息发送到一个URL,跟POST类似,但不常用;
6. Delete:删除URL指定的资源;
7. TRACE:调用一个远程应用层请求消息回路。发出这个消息的用户终端除了收到原来的消息内容以外,还得到消息在Internet上的传送路径。
最常用的请求类型是GET和POST。我们在访问网页时就会向服务器发出如下GET请求:
GET / HTTP/1.1
accept-charset: UTF-8
accept-language: ch
accept: text/vnd.wap.wml, */*, image/bmp, text/html
user-agent: UP.Browser/3.1-UPG1 UP.Link/3.2
host: www.wantsoft.com
……
其中粗体的部分是HTTP消息头,这里我们忽略了一些与我们关系不大的消息头。
accept-charset: 用户终端支持的字符集
accept-language: 用户终端目前使用的语言
accept: 用户终端可以接受的MIME文件类型
user-agent: 用户终端供应商提供的终端描述信息
host: 请求信息发送到的域名
如果该URL合法的话,服务器的响应会是这样的:
HTTP/1.1 200 OK
Server: www/5.0
Date: Fri, 26 Oct 2000 12:15:23 GMT
Connection: Keep-Alive
Content-Length: 1211
Content_Type: text/vnd.wap.wml
Last-Modified: Mon, 22 Oct 2000 18:19:24 GMT
<?xml version=”1.0”>
<!<!DOCTYPE wml PUBLIC “-//WAPFORUM//DTD WML 1.1//EN”
“http://www.wapforum.org/DTD/wml_1.1.xml”>
……
这个响应信息里包括了响应的数字代码和文本描述,然后是一组消息头域。
Server: 发出响应的服务器
Date: 响应发出的时间
Connection: 指示用户终端保持连接
Content-Length: 响应信息的长度,从DECK的第一个”<“字符开始计算
Content_Type: 响应的MIME类型
Last-Modified: 响应中DECK的最后修改时间
当用户终端接收到响应以后,会对其状态信息和消息头进行解码,然后决定对响应做出什么样的动作。如果收到OK响应,一般会把消息本体里的内容显示在屏幕上。
了解了HTTP消息和头域的含义之后,我们就可以用CHttpConnection类来实现Get方法。
BOOL GetRequest(LPCTSTR lpszURL, // 如:www.wantsoft.com
LPCTSTR lpszObjectName, // 如:index.asp
LPCTSTR lpszReferer, // 如:/modify-new.htm
OUT CString &csResponse) //output information
{
BOOL bRet = FALSE;
CString csHeaders, csOptionalData = “”;
//构造GET的头域
csHeaders += “Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, */*n”;
csHeaders += “Referer: http://“;
csHeaders += lpszURL;
csHeaders += lpszReferer;
csHeaders += “n”;
csHeaders += “Accept-Language: zh-cn,en-us;q=0.5n”;
csHeaders += “Content-Type: application/x-www-form-urlencodedn”;
csHeaders += “Proxy-Connection: Keep-Aliven”;
csHeaders += “User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; .NET CLR 1.0.3705; .NET CLR 1.1.4322)n”;
csHeaders += “Host: “;
csHeaders += lpszURL;
csHeaders += “n”;
csHeaders += “Pragma: no-cachen”;
csHeaders += “rn”;
CHttpFile* pMyHttpFile = NULL;
CHttpConnection* pConnection = NULL;
CInternetSession mySession;
try
{
mySession.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 10*1000);
pConnection = mySession.GetHttpConnection(_T(lpszURL));
pMyHttpFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_GET, lpszObjectName);
if ( pMyHttpFile->SendRequest(csHeaders,
(LPVOID)(LPCTSTR)csOptionalData, csOptionalData.GetLength()) )
{
DWORD dwStatus;
DWORD dwBuffLen = sizeof(dwStatus);
pMyHttpFile->QueryInfo(HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwBuffLen);
if ( HTTP_STATUS_OK == dwStatus )
{
csResponse.Empty ();
CString myData;
while ( pMyHttpFile->ReadString ( myData ) )
{
csResponse += myData;
}
bRet = TRUE;
}
}
}
catch ( CInternetException* pEx )
{
bRet = FALSE;
TCHAR szErr[1024]={0};
pEx->GetErrorMessage(szErr,1024);
pEx->Delete();
}
if ( pMyHttpFile )
{
pMyHttpFile->Close();
delete pMyHttpFile;
}
if ( pConnection )
{
pConnection->Close();
delete pConnection;
}
mySession.Close();
return bRet;
}
把文件通过GET方法保存到本地的代码如下:
BOOL SaveFile(LPCTSTR lpszURL, // 如:www.wantsoft.com
LPCTSTR lpszObjectName, // 如:/main.gif
LPCTSTR lpszReferer, // 如:/index.asp
CString &lpszFileName)
{
CInternetSession mySession;
CHttpConnection *pConnection = NULL;
CHttpFile *pMyHttpFile = NULL;
DWORD dwRet, dwRead =1;
BOOL bRet = FALSE;
char szBuff[1024*100];
CString strFileName;
try
{
mySession.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 10*1000);
pConnection = mySession.GetHttpConnection(_T(lpszURL));
pMyHttpFile = pConnection->OpenRequest( CHttpConnection::HTTP_VERB_GET,lpszObjectName);
pMyHttpFile->SendRequest();
pMyHttpFile->QueryInfoStatusCode(dwRet);
//如果该对象GET成功
if (dwRet == HTTP_STATUS_OK)
{
memset( szBuff, 0, sizeof(szBuff));
dwRead= pMyHttpFile->Read(szBuff,sizeof(szBuff)-1);
DWORD mRet = 0;
HANDLE hFile;
lpszFileName = strFileName;
if (leaf::IsFileExist(strFileName))
(leaf::DeleteFilePedding(strFileName,FALSE));
hFile=CreateFile(lpszFileName,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,Create_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
WriteFile(hFile,szBuff,dwRead,&mRet,NULL);
while(dwRead > 0)
{
dwRead= pMyHttpFile->Read(szBuff,sizeof(szBuff)-1);
WriteFile(hFile,szBuff,dwRead,&mRet,NULL);
}
CloseHandle(hFile);
bRet = TRUE;
}
else
{
bRet = FALSE;
}
}
catch ( CInternetException* pEx )
{
bRet = FALSE;
TCHAR szErr[1024]={0};
pEx->GetErrorMessage(szErr,1024);
pEx->Delete();
}
if ( pMyHttpFile )
{
pMyHttpFile->Close();
delete pMyHttpFile;
}
if ( pConnection )
{
pConnection->Close();
delete pConnection;
}
mySession.Close();
return bRet;
}
本文版权属于《Visual C++网络游戏建模与实现》作者苏羽和http://www.wantsoft.com共同所有,引用者请务必保留本行版权信息,否则作者苏羽和http://www.wantsoft.com保留追究的权利。