zoukankan      html  css  js  c++  java
  • wininet异步InternetReadFile和超时相关问题

    wininet是对socket的封装

    主要流程为创建,连接,发送,接收,关闭几个过程

    所以在回调函数InternetStatusCallback中可以检测到dwInternetStatus

    #define INTERNET_STATUS_HANDLE_CREATED          60

    #define INTERNET_STATUS_CONNECTING_TO_SERVER    20
    #define INTERNET_STATUS_CONNECTED_TO_SERVER     21

    #define INTERNET_STATUS_SENDING_REQUEST         30
    #define INTERNET_STATUS_REQUEST_SENT            31


    #define INTERNET_STATUS_RECEIVING_RESPONSE      40
    #define INTERNET_STATUS_RESPONSE_RECEIVED       41

    #define INTERNET_STATUS_REQUEST_COMPLETE        100


    #define INTERNET_STATUS_CLOSING_CONNECTION      50
    #define INTERNET_STATUS_CONNECTION_CLOSED       51

    所以有的时候在设置超时时候不好用 因为只是设置了一个过程的超时整体超时还是不好用

    如超时有

    #define INTERNET_OPTION_CONNECT_TIMEOUT         2

    #define INTERNET_OPTION_CONTROL_SEND_TIMEOUT    INTERNET_OPTION_SEND_TIMEOUT
    #define INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT INTERNET_OPTION_RECEIVE_TIMEOUT
    #define INTERNET_OPTION_DATA_SEND_TIMEOUT       7
    #define INTERNET_OPTION_DATA_RECEIVE_TIMEOUT    8

    应该设置各个流程的超时如:

    InternetSetOption(NULL, INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT, &dwTimeout, sizeof(DWORD));

    但是每个流程超时设置后应答时间和预期还是不一样。可能有几种原因,

    1.各个流程不是按照最长流程超时返回,所以有的流程没有花费timeout超时已经返回

    2.设置超时还不够完整 还有别的流程需要设置超时

    3.设置超时失效http://support.microsoft.com/kb/176420也许是微软BUG

    关于异步wininet网上都说要用InternetReadFileEx而不用InternetReadFile但是我试了一下两个函数其实一样只是参数不一样罢了
    其实在使用该两个函数的时候经常会返回 重叠 I/O 操作在进行中的错误,是http缓冲区正在读数据。
     
    当没调用一次InternetReadFile 就会发现回调函数发送一次INTERNET_STATUS_RECEIVING_RESPONSE  接收数据的信号
    首先在InternetReadFile要取得读取的数据大小用 ret = HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH,  szContentLength, &length,&index); HTTP_QUERY_CONTENT_LENGTH为数据大小。
    主要在收到回调的两个地方来调用InternetReadFile 一是 INTERNET_STATUS_REQUEST_COMPLETE 当数据量比较小的时候只需要读一次就可以返回
    所有数据 但数据量比较大的时候需要等INTERNET_STATUS_RESPONSE_RECEIVED  通知,不论数据量多大只需要这两个过程足够,而不是想象的可以有多次
    INTERNET_STATUS_RESPONSE_RECEIVED 
    一个完整小数据量流程为:
    #define INTERNET_STATUS_HANDLE_CREATED          60
    #define INTERNET_STATUS_CONNECTING_TO_SERVER    20
    #define INTERNET_STATUS_CONNECTED_TO_SERVER     21
    #define INTERNET_STATUS_SENDING_REQUEST         30
    #define INTERNET_STATUS_REQUEST_SENT            31
    #define INTERNET_STATUS_RECEIVING_RESPONSE      40
    #define INTERNET_STATUS_RESPONSE_RECEIVED       41
    #define INTERNET_STATUS_REQUEST_COMPLETE        100
    一个完整大数据量流程为:
    #define INTERNET_STATUS_HANDLE_CREATED          60
    #define INTERNET_STATUS_CONNECTING_TO_SERVER    20
    #define INTERNET_STATUS_CONNECTED_TO_SERVER     21
    #define INTERNET_STATUS_SENDING_REQUEST         30
    #define INTERNET_STATUS_REQUEST_SENT            31
    #define INTERNET_STATUS_RECEIVING_RESPONSE      40
    #define INTERNET_STATUS_RESPONSE_RECEIVED       41
    #define INTERNET_STATUS_REQUEST_COMPLETE        100
    #define INTERNET_STATUS_RECEIVING_RESPONSE      40
    #define INTERNET_STATUS_RESPONSE_RECEIVED       41
    但大数据量比较大的时候就会出现一个问题:
    分两个InternetReadFile怎么把HTTP_QUERY_CONTENT_LENGTH分成两块呢?
    我试了多种方法:
    1。InternetQueryDataAvailable(hRequest,&length,0,0);
    取得可用数据长度但是失败了。
    2.通过回调函数中的lpvStatusInformation取得数据还是不对
     
    通过调用InternetReadFile会发现虽然返回值是错误(重叠 I/O 操作在进行中的错误)但是数据buffer中时有数据的也就是说已经读了一部分
    最后经过调查和尝试发现前两种情况返回的长度不是读取的数据的长度而是取得字符串的长度,为查找''结束符返回的长度。最后经过尝试发现
    在第一次InternetReadFile把申请的HTTP_QUERY_CONTENT_LENGTH数据全部传入
    在第二次InternetReadFile传入buffer+strlen(buffer1)惊奇的发现好用了。。。。
     
  • 相关阅读:
    地税某数据库异常重启和重启后数据库运行缓慢问题的解决过程
    Oracle 索引 详解
    oracle数据库优化基本概念
    oracle物理读和逻辑读
    SQL 优化之该走索引却不走索引的分析(二)
    数据仓库中的分区修剪
    查询低效率的sql语句
    oracle优化的几个简单步骤
    VBS类似于ceil的函数
    ruby符号的应用
  • 原文地址:https://www.cnblogs.com/Neu400753645/p/3476430.html
Copyright © 2011-2022 走看看