Ответ 1
Win32 предоставляет функции Internet*
.
http://msdn.microsoft.com/en-us/library/aa385473(VS.85).aspx
Вам нужно будет сделать (IIRC, я не касался этих API за 10 лет) InternetOpenURL
и InternetReadFile
.
Нет ли "высокоуровневых" HTTP-библиотек для родного C/С++ в Win32, или я просто ищу в неправильных местах?
Под "high-level" я подразумеваю API, который позволяет мне делать HTTP-запросы/ответы HTTP на С++ с "примерно тем же" уровнем абстракции, что и .NET framework (но обратите внимание, что использование С++/CLI не является вариантом для меня).
Как сделать что-то вроде этого (примерно с таким же количеством кода) в C/С++ в Win32 без использования .NET? В качестве ссылки я включаю образец кода, чтобы показать, как я сделаю это на С#.
byte[] fileBytes = null;
bool successfulDownload = false;
using (WebClient client = new WebClient())
{
WebProxy proxy = WebProxy.GetDefaultProxy();
client.Proxy = proxy;
tryAgain:
try
{
fileBytes = client.DownloadData(fileUrl);
successfulDownload = true;
}
catch (WebException wEx)
{
if (wEx.Response != null && wEx.Response is HttpWebResponse)
{
string username = null, password = null;
bool userCanceled = false;
HttpStatusCode statusCode = ((HttpWebResponse)wEx.Response).StatusCode;
switch (statusCode)
{
case HttpStatusCode.ProxyAuthenticationRequired:
// This is just a convenience function defined elsewhere
GetAuthenticationCredentials(fileUrl, true,
out username, out password, out userCanceled);
if (!userCanceled)
{
client.Proxy.Credentials = new NetworkCredential(username, password);
goto tryAgain;
}
break;
case HttpStatusCode.Unauthorized:
// This is just a convenience function defined elsewhere
GetAuthenticationCredentials(fileUrl, false,
out username, out password, out userCanceled);
if (!userCanceled)
{
client.Credentials = new NetworkCredential(username, password);
goto tryAgain;
}
break;
}
}
}
}
Win32 предоставляет функции Internet*
.
http://msdn.microsoft.com/en-us/library/aa385473(VS.85).aspx
Вам нужно будет сделать (IIRC, я не касался этих API за 10 лет) InternetOpenURL
и InternetReadFile
.
Я думаю, libcurl соответствует этим требованиям. И затем некоторые.
В этом примере показано, как получить страницу HTTP, сохраняя ее только в памяти. Это немного больше кода, чем ваш пример, но он в C.
Помимо libcurl/curlpp (который является гибким и мощным, но я нахожу очень... clunky) есть две библиотеки С++, на которые я слежу. Оба являются совершенно новыми и основаны на Boost:: ASIO. Тем не менее, ни поддержка прокси (насколько я могу сказать).
cpp-netlib (blog) является возможно, более зрелый (я знаю, что у него было какое-то реальное тестирование), но в настоящее время не хватает тайм-аутов (я над этим работаю!). Пример:
network::http::request request("http://google.com");
network::http::client client;
network::http::response response;
response = client.get(request);
if (response.status() == 200)
{
std::cout << body(response));
}
Urdl (документация) написана создатель ASIO и имеет таймауты (но был объявлен только в прошлом месяце). Он использует другую модель, предпочитая работать с потоками:
urdl::istream is("http://google.com");
std::string line;
while (std::getline(is, line))
{
std::cout << line << std::endl;
}
Я согласен с тем, что С++ не имеет большой поддержки HTTP, но обе эти библиотеки показывают многообещающие перспективы.
POCO также имеет межплатформенные сетевые компоненты.
Примеры предоставляют FTP-программу как-то вроде этого (это без ошибок проверки ошибок)
Poco::Net::FTPStreamFactory::registerFactory();
std::ofstream localFile(inputFile, std::ios_base::out | std::ios_base::binary);
Poco::URI uri(inputURL);
std::auto_ptr<std::istream> ptrFtpStream(Poco::Net::URIStreamOpener::defaultOpener().open(uri));
Poco::StreamCopier::copyStream(*ptrFtpStream.get(), localFile);
Вы не, глядя в неправильные места. Это просто печальная реальность. Вот почему С++-оболочка для libcurl называется curlpp.
Ниже приведена example о том, как извлечь веб-страницу и распечатать ее в потоке stdout.
#include <curlpp/curlpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
using namespace curlpp::options;
int main(int, char **)
{
try
{
// That all that is needed to do cleanup of used resources (RAII style).
curlpp::Cleanup myCleanup;
// Our request to be sent.
curlpp::Easy myRequest;
// Set the URL.
myRequest.setOpt<Url>("http://example.com");
// Send request and get a result.
// By default the result goes to standard output.
myRequest.perform();
}
catch(curlpp::RuntimeError & e)
{
std::cout << e.what() << std::endl;
}
catch(curlpp::LogicError & e)
{
std::cout << e.what() << std::endl;
}
return 0;
}
Часть Qt-библиотеки, QtNetwork, также является возможностью.
Другая возможность:
http://pion.org/projects/pion-network-library
а другой: