我是靠谱客的博主 高高诺言,最近开发中收集的这篇文章主要介绍Windows平台利用wininet做的HTTP的GET和POST,支持HTTPS,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

                          By Fanxiushu  2014 转载或引用请注明原作者   。

C++开发中,实现HTTP的代码总是比其他开发语言麻烦,现提供 Windows平台下,利用wininet实现的HTTP,支持HTTPS。

希望对还在坚持使用C++开发HTTP通讯的朋友有一小点帮助.


///头文件

/ By Fanxiushu 2014-04-27
#pragma once
///GET
struct http_get_param
{
    const char*        url;
    const char*        option_hdr;
    int                trans_timeout;
    //

    const char*        file_path;

};

int http_downfile(http_get_param * hgp);

/ POST
struct http_post_part
{
    /
    const char*   name;
    const char*   filename;

    char*         data;
    int           data_len;
};

struct http_post_param
{
    const char*         url;
    const char*         option_hdr;
    int                 trans_timeout;
    
    http_post_part*     parts;
    int                 parts_count;

    char*               res_buf;
    int                 res_len;
};

int http_postdata(http_post_param* hpp);

///实现文件, 实现文件的底部是调用实例。

/// By Fanxiushu 2014-04-27

#include <WinInet.h>
#pragma comment(lib,"wininet.lib")
#include "httpclient.h"

struct __http_data_t
{
    HANDLE hEvt;
    HINTERNET hUrl;
};

static void CALLBACK InternetStatusCallback(
    _In_  HINTERNET hInternet,
    _In_  DWORD_PTR dwContext,
    _In_  DWORD dwInternetStatus,
    _In_  LPVOID lpvStatusInformation,
    _In_  DWORD dwStatusInformationLength
    )
{
    __http_data_t* data = (__http_data_t*)dwContext;
    
//        printf("**dwInternetStatus=%dn", dwInternetStatus);
    if (dwInternetStatus == INTERNET_STATUS_REQUEST_COMPLETE){
        INTERNET_ASYNC_RESULT* res = (INTERNET_ASYNC_RESULT*)lpvStatusInformation;
        data->hUrl = (HINTERNET)res->dwResult;
        SetEvent(data->hEvt);
    }
    else if (dwInternetStatus == INTERNET_STATUS_HANDLE_CREATED){
        INTERNET_ASYNC_RESULT* res = (INTERNET_ASYNC_RESULT*)lpvStatusInformation;
        data->hUrl = (HINTERNET)res->dwResult;
    }
}

int http_downfile( http_get_param * hgp )
{
    if (!hgp || !hgp->url || !hgp->file_path) return -1;

    ///
    DWORD flags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE;

    char dns[512] = "";
    char uri_path[8192] = "";
    URL_COMPONENTS uc;
    memset(&uc, 0, sizeof(uc));
    uc.dwStructSize = sizeof(uc);
    uc.lpszHostName = dns;
    uc.dwHostNameLength = 512;
    uc.dwUrlPathLength = 8192;
    uc.lpszUrlPath = uri_path;
    InternetCrackUrl(hgp->url, 0, 0, &uc);

    if (uc.nScheme == INTERNET_SCHEME_HTTPS)
        flags |= (SECURITY_IGNORE_ERROR_MASK |
        SECURITY_INTERNET_MASK | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
        INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
        INTERNET_FLAG_RELOAD);

    /
    HINTERNET hSession = NULL;
    hSession = InternetOpen("HTTP.GetData-UserAgent", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
    if (!hSession){
        log_printf("http_downfile: InternetOpen Error <%d>n", GetLastError());
        return -1;
    }
    InternetSetStatusCallback(hSession, InternetStatusCallback);
    /
    HANDLE hEvt = CreateEvent(NULL, FALSE, FALSE, NULL);
    __http_data_t data; data.hEvt = hEvt; data.hUrl = NULL;

    HINTERNET hConnect = InternetConnect(hSession, dns, uc.nPort, "", "", INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)&data );
    if (!hConnect && GetLastError() == ERROR_IO_PENDING){
        DWORD ret = ::WaitForSingleObject(hEvt, hgp->trans_timeout * 1000);
        hConnect = data.hUrl;
    }
    if (!hConnect){
        log_printf("http_downfile: Connect [%s:%d] Err<%d>n", dns, uc.nPort, GetLastError());
        InternetCloseHandle(hSession);
        CloseHandle(hEvt);
        return -1;
    }

    HINTERNET hRequest = HttpOpenRequest(hConnect, "GET", uri_path, HTTP_VERSION, NULL, NULL, flags, (DWORD_PTR)&data);
    if (!hRequest && GetLastError() == ERROR_IO_PENDING ){
        DWORD ret = ::WaitForSingleObject(hEvt, hgp->trans_timeout * 1000);
        hRequest = data.hUrl;
    }
    if (!hRequest){
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hSession);
        CloseHandle(hEvt);
        log_printf("http_downfile: Open URL [%s] err=%d.n", hgp->url, GetLastError());
        return -1;
    }

    //
    if (uc.nScheme == INTERNET_SCHEME_HTTPS){// 忽略证书错误
        BOOL f;
        DWORD flags = 0; DWORD len = sizeof(flags);
        f = InternetQueryOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &flags, &len);
        flags |= (SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_WRONG_USAGE);
        f = InternetSetOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
        if (!f){
            log_printf("Warning: Set HTTPS Flags Error err=%dn", GetLastError());
        }
    }
    //
    BOOL ff = HttpSendRequest(hRequest, hgp->option_hdr, hgp->option_hdr?strlen(hgp->option_hdr):0, NULL, 0 );
    if (!ff && GetLastError() == ERROR_IO_PENDING){
        if (::WaitForSingleObject(hEvt, hgp->trans_timeout * 1000) == WAIT_OBJECT_0) ff = TRUE;
    }
    if (!ff){
        log_printf("http_downfile:  HttpSendRequest Err=%dn",GetLastError() );
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hSession);
        CloseHandle(hEvt);
        return -1;
    }

    /
    FILE* fp = fopen(hgp->file_path, "wb");
    if (!fp){
        log_printf("http_downfile: Can not Create Local File [%s]n", hgp->file_path );
        InternetCloseHandle(hRequest); InternetCloseHandle(hConnect);  InternetCloseHandle(hSession);
        CloseHandle(hEvt); return -1;
    }

    DWORD total_len = 0; DWORD _sz_len = sizeof(DWORD);
    HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &total_len, &_sz_len, NULL);

    int ret = 0; DWORD cur_len = 0;
    ///
    while (true){
        char buf[16 * 1024];
        DWORD bytes = 0;
        data.hUrl = 0;
        INTERNET_BUFFERS ib; memset(&ib, 0, sizeof(ib));
        ib.dwStructSize = sizeof(INTERNET_BUFFERS);
        ib.dwBufferLength = sizeof(buf)-1;
        ib.lpvBuffer = buf;

        BOOL ff = InternetReadFileEx(hRequest, &ib, IRF_ASYNC, (DWORD_PTR)&data);
        if (!ff){
            if (GetLastError() == ERROR_IO_PENDING){
                if (::WaitForSingleObject(data.hEvt, hgp->trans_timeout * 1000) != WAIT_OBJECT_0){
                    ret = -1; break;
                }
                
            }
            else{
                ret = -1; break;
            }
        }
        bytes = ib.dwBufferLength;
        if (bytes == 0)break;
        
        if (fwrite(buf, 1, bytes, fp) != bytes){
            log_printf("http_downfile: Local Disk Error Can not Write Data.n");
            ret = -1;
            break;
        }
        cur_len += bytes; 
        ///progress
        if (total_len > 0){

        }
        /
        //    buf[bytes]=0; printf( "%s",buf );
    }

    InternetCloseHandle(hRequest);
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hSession);
    CloseHandle(hEvt);

    
    ::fclose(fp);
    if (ret < 0){
        remove(hgp->file_path);
    }
    
    return ret;
}

int http_postdata( http_post_param* hpp )
{
    const char* url = hpp->url;
    const char* option_hdr = hpp->option_hdr;
    hpp->res_buf = NULL;
    hpp->res_len = 0;
    /
    DWORD flags = INTERNET_FLAG_KEEP_CONNECTION| INTERNET_FLAG_NO_CACHE_WRITE;
    int i;

    char dns[512] = "";
    char uri_path[8192] = "";
    URL_COMPONENTS uc;
    memset(&uc, 0, sizeof(uc));
    uc.dwStructSize = sizeof(uc);
    uc.lpszHostName = dns;
    uc.dwHostNameLength = 512;
    uc.dwUrlPathLength = 8192;
    uc.lpszUrlPath = uri_path;
    InternetCrackUrl(url, 0, 0, &uc);
//    printf("%s -> %d -> %sn", dns, uc.nPort, uri_path);

    if (uc.nScheme == INTERNET_SCHEME_HTTPS)
        flags |= (SECURITY_IGNORE_ERROR_MASK |
                 SECURITY_INTERNET_MASK | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
                 INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
                 INTERNET_FLAG_RELOAD);
    //

    HINTERNET hSession = NULL;
    HINTERNET hConnect = NULL;
    HINTERNET hRequest = NULL;
    hSession = InternetOpen("HTTP.PostData-UserAgent", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
    if (!hSession){
        log_printf("http_postdata: InternetOpen Error <%d>n", GetLastError());
        return -1;
    }
    InternetSetStatusCallback(hSession, InternetStatusCallback);
    /
    HANDLE hEvt = CreateEvent(NULL, FALSE, FALSE, NULL);
    __http_data_t hd; hd.hEvt = hEvt; hd.hUrl = NULL;
    hConnect = InternetConnect(hSession, dns, uc.nPort, "", "", INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)&hd);
    if (!hConnect && GetLastError() == ERROR_IO_PENDING){
        DWORD ret = ::WaitForSingleObject(hEvt, hpp->trans_timeout * 1000);
        hConnect = hd.hUrl;
    }
    if (!hConnect){
        log_printf("http_postdata: Connect [%s:%d] Err<%d>n", dns, uc.nPort, GetLastError());
        InternetCloseHandle(hSession);
        CloseHandle(hEvt);
        return -1;
    }

    hRequest = HttpOpenRequest(hConnect, "POST", uri_path, HTTP_VERSION, NULL, NULL, flags,  (DWORD_PTR)&hd );
    if (!hRequest && GetLastError() == ERROR_IO_PENDING){
        DWORD ret = ::WaitForSingleObject(hEvt, hpp->trans_timeout * 1000);
        hRequest = hd.hUrl;
    }
    if (!hRequest){
        log_printf("http_postdata: HttpOpenRequest [%s:%d] Err<%d>n", dns, uc.nPort, GetLastError());
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hSession);
        CloseHandle(hEvt);
        return -1;
    }
    //
    if (uc.nScheme == INTERNET_SCHEME_HTTPS){// 忽略证书错误
        BOOL f;
        DWORD flags = 0; DWORD len = sizeof(flags);
        f = InternetQueryOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &flags, &len);
        flags |= (SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_WRONG_USAGE );
        f = InternetSetOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
        if (!f){
            log_printf("Warning: Set HTTPS Flags Error err=%dn", GetLastError() );
        }
    }
    //

    LPSTR boundary = "$$$-----------------------------xiuxiu2014.03-13%%$$$$----()***kk===";
    ///
    LPSTR accept = "Accept: text/html,application/xhtml+xml,application/xml,text/plain;q=0.9,*/*;q=0.8";
    LPSTR accept_lan = "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3";
//    LPSTR accept_encoding = "Accept-Encoding: gzip, deflate";
    char content_type[256];
    sprintf(content_type, "Content-Type: multipart/form-data; boundary=%s", boundary);

    HttpAddRequestHeaders(hRequest, content_type, -1, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
    HttpAddRequestHeaders(hRequest, accept, -1, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
    HttpAddRequestHeaders(hRequest, accept_lan, -1, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
    //
//    HttpAddRequestHeaders(hRequest, accept_encoding, -1, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE); //不接受编码

    //添加附加头
    if (option_hdr){
        HttpAddRequestHeaders(hRequest, option_hdr, -1, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
    }
    //
    char first_boundary[256];
    char end_boundary[256];
    char delimiter[256];
    sprintf_s(first_boundary, "--%srn", boundary);     int fb_len = strlen(first_boundary);
    sprintf_s(delimiter, "rn--%srn", boundary);      int del_len = strlen(delimiter);
    sprintf_s(end_boundary, "rn--%s--rn", boundary); int eb_len = strlen(end_boundary);

    struct arr_data{
        const char* data;
        int data_len;
        string str;
        arr_data(const char* d, int l) :data(d), data_len(l){}
        arr_data(const string& o) { str = o;  data = str.c_str(); data_len = str.length(); }
        arr_data(const arr_data& o){ data = o.data; data_len = o.data_len; str = o.str; if (!str.empty()){ data = str.c_str(); data_len = str.length(); } }
    };
    list<arr_data> data_array;
    unsigned int id_idx = 0;

    ///
    char* content_subtype = "Content-Type: application/octet-streamrnrn";
    int subtype_len = strlen(content_subtype);

    data_array.push_back(arr_data(first_boundary, fb_len )); // first boundary

    DWORD upLen = fb_len + eb_len;

    for (i = 0; i < hpp->parts_count && hpp->parts ; ++i ){
        http_post_part* ps = &(hpp->parts[i]);
        char name[1024]; char filename[1024];
        if (ps->name)sprintf(name, "; name="%s"", ps->name);
        else { sprintf(name, "; name="NAME%d"", id_idx++); }
        if (ps->filename)sprintf(filename, "; filename="%s"", ps->filename);
        else strcpy(filename, "");
        string ctx = string("Content-Disposition: form-data") + name + filename + "rn";
        
        if ( i != 0  ){ //不是第一个段,多个段之间的分割

            data_array.push_back( arr_data(delimiter, del_len) );  upLen += del_len;
        }
        
        data_array.push_back( arr_data(ctx) ); upLen += ctx.length(); //content_dispos
        data_array.push_back(arr_data(content_subtype, subtype_len)); upLen += subtype_len; // content_subtype
        if (ps->data && ps->data_len > 0){
            data_array.push_back(arr_data(ps->data, ps->data_len)); upLen += ps->data_len;  // DATA
        }
        //
    }

    data_array.push_back(arr_data(end_boundary, eb_len)); // end boundary

    INTERNET_BUFFERS bufIn;
    memset(&bufIn, 0, sizeof(bufIn));
    bufIn.dwStructSize = sizeof(bufIn);
    bufIn.dwBufferTotal = upLen;
    BOOL ret = HttpSendRequestEx(hRequest, &bufIn, NULL, 0, (DWORD_PTR)&hd);
    if (!ret && GetLastError() == ERROR_IO_PENDING){
        if (::WaitForSingleObject(hEvt, hpp->trans_timeout * 1000) == WAIT_OBJECT_0) ret = TRUE;
    }
    if (!ret){
        log_printf("http_postdata: HttpSendRequestEx [%s:%d] Err<%d>n", dns, uc.nPort, GetLastError());
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hSession);
        CloseHandle(hEvt);
        return -1;
    }

    //
    list<arr_data>::iterator yy;
    for (yy = data_array.begin(); yy != data_array.end(); ++yy ){
        DWORD bytes = 0;
        arr_data* d = &(*yy);
        ret = InternetWriteFile(hRequest, d->data,d->data_len, &bytes);
        if (!ret && GetLastError() == ERROR_IO_PENDING){
            if (::WaitForSingleObject(hEvt, hpp->trans_timeout * 1000) == WAIT_OBJECT_0) ret = TRUE;
        }
        if (!ret){
            log_printf("http_postdata: InternetWriteFile [%s:%d] Err<%d>n", dns, uc.nPort, GetLastError());
            InternetCloseHandle(hRequest);
            InternetCloseHandle(hConnect);
            InternetCloseHandle(hSession);
            CloseHandle(hEvt);
            return -1;
        }
    }

    ///
    ret = HttpEndRequest(hRequest, 0, 0, (DWORD_PTR)&hd);
    if (!ret && GetLastError() == ERROR_IO_PENDING){
        if (::WaitForSingleObject(hEvt, hpp->trans_timeout * 1000) == WAIT_OBJECT_0) ret = TRUE;
    }
    if (!ret){
        log_printf("http_postdata: HttpEndRequest errn");
    }
     read response
    DWORD size = 4096;
    char* pbuf = (char*)malloc(size);

    DWORD total_len = 0; DWORD _sz_len = sizeof(DWORD);

    HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &total_len, &_sz_len, NULL);

    ret = 0; DWORD cur_len = 0;
    if (!pbuf){
        ret = -1; goto L;
    }
    ///
    while (true){
        char buf[8 * 1024];
        DWORD bytes = 0;
        hd.hUrl = 0;
        INTERNET_BUFFERS ib; memset(&ib, 0, sizeof(ib));
        ib.dwStructSize = sizeof(INTERNET_BUFFERS);
        ib.dwBufferLength = sizeof(buf)-1;
        ib.lpvBuffer = buf;

        BOOL ff = InternetReadFileEx(hRequest, &ib, IRF_ASYNC, (DWORD_PTR)&hd);
        if (!ff){
            if (GetLastError() == ERROR_IO_PENDING){
                if (::WaitForSingleObject(hd.hEvt, hpp->trans_timeout * 1000) != WAIT_OBJECT_0){
                    ret = -1;
                    goto L;
                }
                
            }
            else{
                ret = -1;
                goto L;
            }
        }
        bytes = ib.dwBufferLength;
        if (bytes == 0)break;
        
        if (bytes + cur_len >= size-1 ){
            size = cur_len + bytes + 1024 * 8 + 10;
            char* vpp = (char*)realloc(pbuf, size);
            if (!vpp){
                ret = -1;
                goto L;
            }
            pbuf = vpp;
        }

        memcpy(pbuf + cur_len, buf, bytes);
        
        cur_len += bytes; 

        ///progress, 进度
        if (total_len > 0){
            ///
        }
        /
        //    buf[bytes]=0; printf( "%s",buf );
    }
    
    //
    pbuf[cur_len] = '';
    hpp->res_buf = pbuf;
    pbuf = NULL;
    hpp->res_len = cur_len;

L:

    InternetCloseHandle(hRequest);
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hSession);
    CloseHandle(hEvt);
    if (pbuf)free(pbuf);
    
    return ret;
}

#if 1

int main(int argc, char** argv)
{
#if 1    // POST
    http_post_param hp; memset(&hp, 0, sizeof(hp));
    hp.trans_timeout = 20;

    hp.url = "https://passport.csdn.net/account/login?ref=toolbar"; // "https://www.google.com.hk/"; "http://192.168.0.120/tmp_dir";

    http_post_part sc[5]; memset(&sc, 0, sizeof(sc));
    sc[0].name = "Client-UniqueID";  sc[0].data = "ID00001"; sc[0].data_len = 8; //sc.filename = "filename.txt";

    sc[1].name = "DATA";
    sc[1].data = "DATA001"; sc[1].data_len = 7;

    sc[2].name = "ScreenSize";
    sc[2].data = "1366,768"; sc[2].data_len = strlen(sc[2].data);

    /
    hp.parts = sc;
    hp.parts_count = 3; ///
    ///


    http_postdata(&hp); printf("DATA_LEN=%dn%sn", hp.res_len, hp.res_buf);
//    getchar();
    
    if (hp.res_buf)free(hp.res_buf);

#endif

#if 1    /// GET
    http_get_param hgp; memset(&hgp, 0, sizeof(hgp));

    hgp.url = "https://www.google.com.hk/";
    hgp.trans_timeout = 15;
    hgp.file_path = "test.htm";

    http_downfile(&hgp);

#endif


    return 0;
}

#endif


最后

以上就是高高诺言为你收集整理的Windows平台利用wininet做的HTTP的GET和POST,支持HTTPS的全部内容,希望文章能够帮你解决Windows平台利用wininet做的HTTP的GET和POST,支持HTTPS所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部