要进行HTTP访问,需要在stdafx.h包含
#include <afxinet.h>,引入三个类:CInternetSession、CHttpConnection、CHttpFile。
CInternetSession用于打开网络连接(GetHttpConnection),CHttpConnection用以维持网络连接并打开请求(OpenRequest),CHttpFile用以发送请求(SendRequest)。
首先要考虑编码问题——网络上应用最广的是UTF-8编码,而Windows和MFC则是UTF-16编码。MFC访问HTTP获得的可能是UTF-8或GBK,然而MFC的程序内码却可能是UTF-16(这种编码基本不可能出现在Internet),内置的网络访问类并不会自动转码,直接当作CString接收有可能会导致乱码。因此需要写一个转码函数(这个转码函数在ANSI编译时也能正常工作):
CString mbcs2tcs(CStringA astr, bool isutf8)
{
if (isutf8) {
int length = MultiByteToWideChar(CP_UTF8, 0, astr, -1, NULL, 0);
wchar_t *bufnew = new wchar_t[length + 1];
MultiByteToWideChar(CP_UTF8, 0, astr, -1, bufnew, length);
bufnew[length] = 0;
CString wstr(bufnew);
delete []bufnew;
return wstr;
}
else {
return (CString) astr;
}
}
CStringA tcs2mbcs(CString str, bool isutf8)
{
if (isutf8) {
CStringW wstr = (CStringW) str;
int length = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
char *bufnew = new char[length + 1];
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, bufnew, length, NULL, NULL);
bufnew[length] = 0;
CStringA astr(bufnew);
delete []bufnew;
return astr;
}
else {
return (CStringA) str;
}
}
其中用处最广的GET有一个捷径,先建立一个CInternetSession对象,然后用它打开任意的URL(OpenURL)即可返回一个CStdioFile对象(可附带请求头部),通常会是CHttpFile。调用Read()即可获得返回的内容,然后转码显示即可。
void CHttpTestDlg::OnBnClickedRunRequest()
{
UpdateData(true);
try {
CInternetSession inetsess; // CInternetSession
CHttpFile *file = NULL;
file = (CHttpFile*)
inetsess.OpenURL(m_url, 1, INTERNET_FLAG_TRANSFER_ASCII | INTERNET_FLAG_RELOAD,
m_reqheader, _tcslen(m_reqheader));
m_recv = _T(""); // 清空文本框
char buf[1024] = {0};
int ncount;
CStringA ansistr;
while (ncount = file->Read(buf, 1023)) {
buf[ncount] = '\0';
ansistr += buf;
}
m_recv = mbcs2tcs(ansistr, m_isutf8); // 从GB2312转码到wchar_t(如果是ANSI编译则不转码)输出到文本框
file->Close(); // 关闭请求文件
if (file != NULL)
delete file;
inetsess.Close(); // 关闭CInternetSession
}
catch (CException &e) {
m_recv = _T("获取错误");
}
UpdateData(false);
}
运行截图:
要进行POST访问,就要采用逐步的方法了,首先解析输入的URL(AfxParseURL),分出服务器、路径、端口等信息,然后打开HTTP连接(GetHttpConnection),获得CHttpConnection,再从连接打开请求(OpenRequest)向服务器请求路径,获得CHttpFile,然后发送(SendRequest)请求头部和POSTDATA,最后Read()数据,转码显示即可。因为各种原因,POSTDATA也一定要是UTF-8或GBK的,不能是UTF-16。
void CHttpTestDlg::OnBnClickedPostCmd()
{
UpdateData(true);
try {
CInternetSession inetsess; // CInternetSession
CHttpConnection *connect = NULL;
CHttpFile *file = NULL;
{ // POST请求:通过CInternetSession打开HTTP连接,然后再用HTTP连接打开HTTP请求,发送请求
DWORD svctype;
CString srvname;
CString objname;
INTERNET_PORT port;
AfxParseURL(m_url, svctype, srvname, objname, port); // 解析URL,得到服务器名、路径名、端口名等
connect = inetsess.GetHttpConnection(srvname, port); // 建立HTTP连接,到服务器和端口
file = connect->OpenRequest(_T("POST"), objname); // 打开HTTP请求,类型POST,到路径名
// 发送请求,附带头部和附加信息。附加数据必须为ANSI或UTF-8,要进行转换
CStringA postdata = tcs2mbcs(m_postdata, m_isutf8);
LPCSTR postbuffer = (LPCSTR)postdata;
file->SendRequest(m_reqheader, m_reqheader.GetLength(), (LPVOID)postbuffer, strlen(postbuffer));
}
m_recv = _T(""); // 清空文本框
char buf[1024] = {0};
int ncount;
CStringA ansistr;
while (ncount = file->Read(buf, 1023)) {
buf[ncount] = '\0';
ansistr += buf;
}
m_recv = mbcs2tcs(ansistr, m_isutf8); // 从GB2312转码到wchar_t(如果是ANSI编译则不转码)输出到文本框
file->Close();
connect->Close();
if (file != NULL) // 关闭请求文件
delete file;
if (connect != NULL) // 关闭连接
delete connect;
inetsess.Close(); // 关闭CInternetSession
}
catch (CException &e) {
m_recv = _T("获取错误");
}
UpdateData(false);
}
运行截图:
HttpTest.rar
1.09MB
RAR
108次下载