InternetQueryDataAvailable 读取字节数为0的解决方法

来源:互联网 发布:淘宝搜白夜追凶接电话 编辑:程序博客网 时间:2024/05/17 15:04

从远程读取数据时, 一般是调用2个函数的组合 : InternetQueryDataAvailable + InternetReadFile

只有 InternetQueryDataAvailable 查到远端提供了数据, 才用InternetReadFile读取数据.

最近看见一个现象, 远端是有文件的, 有时也下载了一半, 但是再调用InternetQueryDataAvailable, 返回的可操作字节数总是为0

这时, InternetQueryDataAvailable是超时返回的, 不像平时那样, 返回的很快.

这时, 如果是直接调用InternetReadFile, 也只能超时返回.

如下:

        if (!InternetQueryDataAvailable(m_http_request, &dwBytesAvailable, 0, 0))        {            // 有可能是 (getLastError() == NO MORE FILES), 算错误么?            // 下载时, 会出现这种错误码么?            m_http_response.m_bfinal_read_result = FALSE;            eRc = ns_e_http_request_status::err_read_remotefile;            WriteLogEx(L"break 2 FCHttpRequest::proc_http_request()");            goto END_proc_http_request;        }        if (dwBytesAvailable <= 0)        {            m_http_response.m_bfinal_read_result = TRUE;            eRc = ns_e_http_request_status::ok; ///< no more data            WriteLogEx(L"InternetQueryDataAvailable (dwBytesAvailable <= 0)");            goto END_proc_http_request;        }

...


        bReadResult = InternetReadFile(m_http_request, pcBufRead, HTTP_READ_FILE_BUFFER_SIZE, &dwBytesReadBack);        if (!bReadResult)        {            m_http_response.m_bfinal_read_result = FALSE;            eRc = ns_e_http_request_status::err_read_remotefile;            // WriteLogEx(L"break 4 FCHttpRequest::proc_http_request()");            goto END_proc_http_request;        }        if (0 == dwBytesReadBack)        {


但是, 这时再开迅雷或直接在浏览器上下载该url, 是可以下载到本地的.

我猜想我用程序下载和第三方的下载功能有啥区别呢? 

我突然想到了下载时用到的userAgent, 以前也想改改, 但是因为下载组件整理后, 没有亲自看到不能下载的原因,就没动手.


    // Get user-agent used by IE.    std::wstring GenDifferentUserAgent()    {        DWORD  n = 1024;        char   t[1024] = {0};        std::string strSession = "";        std::wstring::size_type nPos = std::wstring::npos;        std::wstring strTemp = L"";        if (m_user_agent.size() <= 0)        {            ObtainUserAgentString(0, t, &n);            strSession = t;            //为了防止服务器停止响应某个固定的Agen, 有必须要使userAgent每次不同            // M$给出的userAgent样例            // Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; InfoPath.1)            // 本地实际得到的userAgent            // Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)            strTemp = ns_base::A2Wex(strSession.c_str());            /// 找到第一个" ("            nPos = strTemp.find(L" (");            if (std::wstring::npos != nPos)            {                strTemp = strTemp.substr(nPos, -1);            }            m_user_agent = ns_base::StringFormatV(L"Mozilla%I64x/4.0%s", (LONGLONG)time(NULL), strTemp.c_str()).c_str();        }        return m_user_agent;    }

HINTERNET FCHttpRequest::create_session_real(){    BOOL                bRc = FALSE;    DWORD               dw_timeout = 30 * 1000; // override the 30 second timeout    std::wstring        strTemp = L"";    std::wstring        s = L"";    HINTERNET           hSession = NULL;    if (m_http_request_header.m_proxy_ip.size() > 0)    {        s = ns_base::StringFormatV(_T("%s:%d"),             m_http_request_header.m_proxy_ip.c_str(),             m_http_request_header.m_proxy_port) ;        hSession = InternetOpen(            m_http_request_header.m_user_agent.c_str(),            INTERNET_OPEN_TYPE_PROXY,             s.c_str(),             NULL,             0);    }    else    {        hSession = InternetOpen(            m_http_request_header.m_user_agent.c_str(),            INTERNET_OPEN_TYPE_DIRECT, // INTERNET_OPEN_TYPE_PRECONFIG,            NULL,            NULL,            0);    }    if (NULL != hSession)    {        // set proxy username and password        if (m_http_request_header.m_proxy_username.size())        {            InternetSetOption(                hSession,                 INTERNET_OPTION_PROXY_USERNAME,                 (LPVOID)(LPCTSTR)m_http_request_header.m_proxy_username.c_str(),                 m_http_request_header.m_proxy_username.size()) ;        }        if (m_http_request_header.m_proxy_password.size())        {            InternetSetOption(                hSession,                 INTERNET_OPTION_PROXY_PASSWORD,                 (LPVOID)(LPCTSTR)m_http_request_header.m_proxy_password.c_str(),                 m_http_request_header.m_proxy_password.size()) ;        }        /// internetreadfile block for long long time, so set timeout to it        bRc = InternetSetOption(hSession, INTERNET_OPTION_RECEIVE_TIMEOUT, &dw_timeout, sizeof(DWORD));        if (!bRc)        {            OutputDebugStringW(L"");        }    }    return hSession;}

ns_e_http_request_status::e_http_request_status FCHttpRequest::DlFilePart(){    ns_e_http_request_status::e_http_request_status eRc = ns_e_http_request_status::unknown;    m_start_tick = GetTickCount();    _ASSERT(NULL != m_pOwner);    eRc = proc_create_session();    if (!IsValidHttpStatus(eRc))    {        goto END_DlFilePart;    }    if (NULL == m_phttp_session)    {        eRc = ns_e_http_request_status::err_create_session;        goto END_DlFilePart;    }    if (IsNeedQuit())    {        eRc = ns_e_http_request_status::owner_cancel;        goto END_DlFilePart;    }    eRc = proc_http_connect();    if (!IsValidHttpStatus(eRc))

改了userAgent后, 当服务器回答没有数据可提供时, 当作错误退出该下载子任务.

由下载失败再重试时, 由于userAgent重新变了一个, 就可以下载数据了.


如果不改userAgent, 即使失败重试, 还会遇到同样的 InternetQueryDataAvailable (dwBytesAvailable == 0)

如果不改userAgent, 通过实验, 发现服务器过一会(大约5~10分钟)才会重新响应 InternetQueryDataAvailable (dwBytesAvailable != 0)


感觉还是http服务器有啥BUG.

暂时先这么解决了, 看以后能不能知道 InternetQueryDataAvailable (dwBytesAvailable == 0)的真正原因.







0 0