MFC进行HTTP访问
acmilan2015/06/12软件综合 IP:四川
要进行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编译时也能正常工作):
<code class="lang-cpp">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;
    }
}</code>

其中用处最广的GET有一个捷径,先建立一个CInternetSession对象,然后用它打开任意的URL(OpenURL)即可返回一个CStdioFile对象(可附带请求头部),通常会是CHttpFile。调用Read()即可获得返回的内容,然后转码显示即可。
<code class="lang-cpp">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);
             
}</code>
运行截图:
捕获ttt.png
捕获ttu.png

要进行POST访问,就要采用逐步的方法了,首先解析输入的URL(AfxParseURL),分出服务器、路径、端口等信息,然后打开HTTP连接(GetHttpConnection),获得CHttpConnection,再从连接打开请求(OpenRequest)向服务器请求路径,获得CHttpFile,然后发送(SendRequest)请求头部和POSTDATA,最后Read()数据,转码显示即可。因为各种原因,POSTDATA也一定要是UTF-8或GBK的,不能是UTF-16。
<code class="lang-cpp">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);
}</code>
运行截图:
捕获ttv.png
attachment icon HttpTest.rar 1.09MB RAR 88次下载

[修改于 9年7个月前 - 2015/06/12 09:50:36]

来自:计算机科学 / 软件综合
1
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
acmilan
进士 学者 笔友
文章
461
回复
2934
学术分
4
2009/05/30注册,5年10个月前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}