【问题标题】:C / C++ - How to download byte by byte (like a file stream) from the web?C / C++ - 如何从网络上逐字节(如文件流)下载?
【发布时间】:2015-08-05 15:07:07
【问题描述】:

我正在用 C 和 C++ 构建一个简单的下载和文件传输管理器,支持暂停和恢复操作。 我寻找一种从给定 URL 逐字节下载的方法,但我能找到的只是对 libcurl 等外部库的引用。我不想要外部库,我想手动读取和写入字节,其方式与仅使用 C/C++ 本机库读取和写入字节到文件(如 C++ 中的 ifstream 和 C 中的 fopen)类似。 我需要的伪代码是:

void download(file, url) {
    file.open();
    url.open();
    set_active(true);
    while( ! pause() ) {
        bytes_read = url.read(byte_array);
        if(bytes_read < 1)
            break;
        file.write(byte_array, bytes_read);
    }
    url.close();
    file.close();
    set_active(false);
}

该伪代码在 C 和 C++ 中如何工作?


编辑:我不想为了学习这两种语言及其本机库的功能和限制的简单兴趣而使用外部库。

编辑 2:结论:这两种语言都没有对 HTTP 操作的本机支持,因此我必须在使用第三方库或从头开始编写 HTTP(和其他几种协议)实现之间做出选择,这是不可靠的。谢谢。

【问题讨论】:

  • C 或 C++ 标准库中没有网络支持。您无法避免使用 some 第三方库。这些都不缺。
  • 您可以创建一个套接字,调用connect(),然后从套接字调用read(),但这并不简单,例如,使用像curl 这样的库会让您的生活变得更轻松假设您必须使用ssl 进行https 连接,那么编写健壮的功能完整代码将非常困难,而libcurl 将帮助您做到这一点等等。此外,使用curl,您无需处理端口号以及返回多少 Ip 的getaddrinfo() 以及哪个有效,对于https,您只需提供urlcurl 就会知道端口为你做任何事情。
  • @IgorTandetnik 我认为套接字 api 是“标准的”,因为它存在于所有主要平台上。为此,他不需要一些第三方库。他需要他的平台提供的东西。如果他想使用套接字通过 http 加载,他可能希望在原始套接字层之上找到 api。大多数操作系统也有“特定于操作系统”的标准 API。
  • 您能否编辑您的问题以解释您为什么不想要第三方 HTTP 库?

标签: c++ c url download stream


【解决方案1】:

您应该使用libcurl 或其他一些HTTP 客户端库(例如libsoup,如果使用GTK)。如果您需要 HTTP 服务器支持,您可以找到相应的库,例如libonion.

您也可以考虑POCOQt5 框架,它们都有HTTP 的东西。

如果您不想使用任何此类 HTTP 3rd 方库,则需要自己重新实现 HTTP。这可能很复杂(以及几个月或几年的工作),因为 HTTP 规范有数百页!处理一些简单的GET 请求很容易,但处理所有的 HTTP 规范很难。

您可以尝试实现您的子集 HTTP,可能某些情况下工作,但您会很容易找到 HTTP服务器或客户端需要更多的 HTTP,...。您的实现将比现有的 HTTP 库更加脆弱和错误...

【讨论】:

  • 你还有 gnome libsoup 库来处理 http 请求响应
  • 我怀疑这会花费数月或数年的时间来快速完成某件事。我的猜测是第一次成功的 GET 需要 3 个小时。最终会令人讨厌的是https和证书等。但是对于不安全的HTTP连接,它并没有那么多工作。
  • 确实如此,但是当您需要分块请求、条件请求等时......事情会变得复杂。
【解决方案2】:

刚刚注意到您不想要外部库的编辑要求。但这里是我在 MSVC 中编写的用于从 Windows 程序下载文件的程序的摘录。

// Windows Header Files:
#include <windows.h>
#include <wininet.h>

// Make internet connection.
HINTERNET hInternetSession = InternetOpen(
        "Microsoft Internet Explorer",          // agent
        INTERNET_OPEN_TYPE_PRECONFIG,           // access
        NULL, NULL, 0);                         // defaults
...

// Make connection to desired page.
HINTERNET hURL = InternetOpenUrl(
        hInternetSession,                       // session handle
        szSors,                                 // URL to access
        NULL, 0, 0, 0);                         // defaults
if (hURL == 0)
    return 0;
...

// Read data into memory buffer.
DWORD dwBytesRead = 0;
BOOL bResult = InternetReadFile(
        hURL,                                   // handle to URL
        (LPSTR)cBuffer,                         // pointer to buffer
        (DWORD)MYBSIZE,                         // size of buffer
        &dwBytesRead);                          // to hold return value
...

InternetCloseHandle(hInternetSession);

我从来没有按照你的要求下载一个字节,但我不明白你为什么不能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-14
    • 2011-03-01
    • 2012-03-07
    相关资源
    最近更新 更多