• WinInet开发中的同步和异步区别


    同步和异步的概念在此就不啰唆了。
    以下载一个文件为例,我们来看看同步的做法:
    1)InternetOpen;
    2)InternetOpenUrl;
    3)HttpQueryInfo;
    4)InternetReadFile;
    5)InternetCloseHandle。
    在第2步和第4步,程序会一直等待,直到函数返回。如果要设置超时,可以使用InternetSetOption(不过好像没什么用)。在很多时候,这个函数是不合适的。比如用户主动要中断下载,却只能等待函数返回。还有,如果是大文件下载,无法想像一次读取上兆字节的数据,需使用断点续传,虽然也可以使用同步函数InternetSetFilePointer来定位网络文件读取位置,但很多服务器是不支持的。如果在手机上使用,还要考虑诸如移动网关的限制等等。
    同步的好处是函数较少,流程清晰,调试也方便。

    再来看看异步的做法。
    1)InternetOpen,需指定是异步;
    2)InternetSetStatusCallback,设置回调;
    3)InternetOpenUrl,需指定回调参数;
    4)WaitForSingObject或WaitForMultipleObjects,接收信号量;
    5)HttpQueryInfo;
    6)InternetReadFileEx,需指定回调参数;
    7)WaitForSingObject或WaitForMultipleObjects,接收信号量;
    8)InternetSetStatusCallback,卸载回调;
    9)InternetCloseHandle。
    可以看出,异步比同步要复杂了不少,重点在于回调函数。在回调中,系统会及时返回各种系统定义的HTTP消息,我们根据这些消息来设置某些信号量。在WaitForSingObject或WaitForMultipleObjects里,等待这些信号(当然也可以等待用户的取消动作)。当有正确的信号返回时,继续往下的操作。
    异步方式下,InternetOpenUrl可以在header头里设置要读取的范围。比如读0到1024的数据,在header头里加入Range: bytes=0-1024/r/n。这种方式保证了断点续传。要注意的是,如果服务器支持断点续传,此时使用HttpQueryInfo得到的状态码是206,而不是200。

    回调函数怎么写啊?看看微软提供的一个例子吧。这个例子是用POST的方式上传数据,比上述下载数据步骤更为麻烦,把InternetOpenUrl这个函数分成更多的函数来处理。有时间再挖挖这个例子。微软这个例子是在一个sendreqexasync.cpp的文件中,在微软的网站上应该可以得到。

    省去其他,我们单单看看回调的写法:
    ......
    void __stdcall Callback(HINTERNET hInternet,
                  DWORD dwContext,
                  DWORD dwInternetStatus,
                  LPVOID lpStatusInfo,
                  DWORD dwStatusInfoLen)
    {
        cout << "Callback dwInternetStatus: " << dwInternetStatus << " Context: " << dwContext << endl;
        cout.flush();

        switch(dwContext)
        {
        case 1: // Connection handle
            if (dwInternetStatus == INTERNET_STATUS_HANDLE_CREATED)
            {
                INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
                hConnect = (HINTERNET)pRes->dwResult;
                cout << "Connect handle created" << endl;
                cout.flush();
                SetEvent(hConnectedEvent);
            }
            break;

        case 2: // Request handle
            switch(dwInternetStatus)
            {
            case INTERNET_STATUS_HANDLE_CREATED:
                {
                    INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
                    hRequest = (HINTERNET)pRes->dwResult;
                    cout << "Request handle created" << endl;
                    cout.flush();
                }
                break;

            case INTERNET_STATUS_REQUEST_SENT:
                {
                    DWORD *lpBytesSent = (DWORD*)lpStatusInfo;
                    cout << "Bytes Sent: " << *lpBytesSent << endl;
                    dwNumBytesComplete += *lpBytesSent;
                }
                break;

            case INTERNET_STATUS_REQUEST_COMPLETE:
                {
                    INTERNET_ASYNC_RESULT *pAsyncRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
                    cout << "Function call finished" << endl;
                    cout << "dwResult: " << pAsyncRes->dwResult << endl;
                    cout << "dwError:  " << pAsyncRes->dwError << endl;
                    cout.flush();
                    SetEvent(hRequestCompleteEvent);
                }
                break;

            case INTERNET_STATUS_RECEIVING_RESPONSE:
                cout << "Receiving Response" << endl;
                cout.flush();
                break;

            case INTERNET_STATUS_RESPONSE_RECEIVED:
                {
                    DWORD *dwBytesReceived = (DWORD*)lpStatusInfo;
                    cout << "Received " << *dwBytesReceived << endl;
                    cout.flush();
                }
            }
        }
    }

  • 相关阅读:
    NLPIR大数据语义系统文本数据分析挖掘平台
    NLPIR:中文语义挖掘是自然语言处理的关键
    NLPIR-JZSearch智能搜索深层挖掘大数据资源
    NLPIR智能Protege知识图谱实现多场景应用
    DotNet加密方式解析--散列加密
    SSO单点登录PHP简单版
    xss框架基础框架实现
    Kafka Offset Storage
    C#如何使用ES
    模拟Vue之数据驱动
  • 原文地址:https://www.cnblogs.com/fengju/p/6173559.html
Copyright © 2020-2023  润新知