Страницы

Поиск по вопросам

четверг, 28 ноября 2019 г.

Отправка GET/POST-запроса средствами чистого C++

#c++ #http


Как реализовать простой GET/POST запрос без использования сторонних библиотек?

Нашел много примеров, но там либо cpp-netlib, либо curl, а мне бы хотелось самому
все это написать, но с сетью в С++ не работал, только через Qt. Было бы очень здорово
увидеть маленький работающий пример :)
    


Ответы

Ответ 1



На "чистом C++" много чего нельзя сделать, потому что стандартная библиотека языка слишком миниатюрная, она не включает достаточно функционала, чтобы работать с HTTP. В какой-то мере "полустандартной" библиотекой является boost (какие-то его библиотеки позже становятся частью стандартной библиотеки), поэтому можно воспользоваться boost::asio. Однако учтите, что это всё равно достаточно низкоуровневая библиотека. Простой HTTP-запрос вы сможете написать в пару строчек, но вы будете вручную разруливать все сотни современных возможностей HTTP: безопасное соединение, сжатие траффика, кэширование и так далее и тому подобное. Я уж молчу про новую версию стандарта. И если вы можете сказать серверу "я не поддерживаю сжатие, давай данные как есть", то проигнорировать HTTPS вы ну никак не сможете. Вы изобретёте велосипед, который никому не будет нужен. Вы станете лучше понимать потроха HTTP, конечно, но кроме как для обучения смысла писать такой код нет. Если вам нужны маленькие и работающие примеры, то посмотрите Debunking Stroustrup's debunking of the myth “C++ is for large, complicated, programs only” — они там есть на всех языках, в том числе несколько на C++, а один из примеров написан самим Страуструпом.

Ответ 2



Я решил проблему так: #include #include #include #include #include #include #include #include #include #include #include #include #include char http[]={"http://"}; char host[]={"localhost"}; char parm[]={"/api/method.php"}; std::string getProtocol( std::string url ) { std::string protocol = ""; int i = 0; for(i = 0; i < url.size(); i++) { if( url[i] != '/' || url[i+1] != '/' ) { protocol += url[i]; } else { protocol += "//"; break; } } return protocol; } std::string getHost( std::string url ) { std::string host = ""; url.replace(0, getProtocol(url).size(), ""); int i = 0; for(i = 0; i < url.size(); i++) { if( url[i] != '/' ) { host += url[i]; } else { break; } } return host; } std::string getAction( std::string url ) { std::string parm = ""; url.replace(0, getProtocol(url).size()+getHost(url).size(), ""); int i = 0; for(i = 0; i < url.size(); i++) { if( url[i] != '?' && url[i] != '#' ) { parm += url[i]; } else { break; } } return parm; } std::string getParams( std::vector< std::pair< std::string, std::string> > requestData ) { std::string parm = ""; std::vector< std::pair< std::string, std::string> >::iterator itr = requestData.begin(); for( ; itr != requestData.end(); ++itr ) { if( parm.size() < 1 ) { parm += ""; } else { parm += "&"; } parm += itr->first + "=" + itr->second; } return parm; } std::string GET( std::string url, std::vector< std::pair< std::string, std::string> > requestData ) { std::string http = getProtocol(url); std::string host = getHost(url); std::string script = getAction(url); std::string parm = getParams( requestData ); char buf[1024]; std::string header = ""; header += "GET "; header += http + host + script + "?" + parm; header += (std::string)" HTTP/1.1" + "\r\n"; header += (std::string)"Host: " + http + host + "/" + "\r\n"; header += (std::string)"User-Agent: Mozilla/5.0" + "\r\n"; //header += (std::string)"Accept: text/html" + "\r\n"; header += (std::string)"Accept-Language: ru,en-us;q=0.7,en;q=0.3" + "\r\n"; header += (std::string)"Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7" + "\r\n"; header += (std::string)"Connection: keep-alive " + "\r\n"; header += "\r\n"; int sock; struct sockaddr_in addr; struct hostent* raw_host; raw_host = gethostbyname( host.c_str() ); if (raw_host == NULL) { std::cout<<"ERROR, no such host"; exit(0); } sock = socket(AF_INET, SOCK_STREAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(80); bcopy( (char*)raw_host->h_addr, (char*)&addr.sin_addr, raw_host->h_length ); if( connect( sock, (struct sockaddr *)&addr, sizeof(addr) ) < 0) { std::cerr<<"connect error"<

Ответ 3



На данный момент в стандарте С++ нет средств для работы с сетью. При помощи библиотеки Boost.Asio (которую собираются включить в стандарт) это можно сделать буквально тремя строчками кода: #define _WIN32_WINNT 0x0A00 #define BOOST_DATE_TIME_NO_LIB #define BOOST_REGEX_NO_LIB #include #include int main() { boost::asio::ip::tcp::iostream stream("httpbin.org", "http"); stream << "GET /ip HTTP/1.1\r\nHost: httpbin.org\r\nConnection: close\r\n\r\n"; std::cout << stream.rdbuf(); } С использованием Boost.Beast: #include #include #include #include int main() { boost::asio::io_service io_service; boost::asio::ip::tcp::resolver resolver(io_service); boost::asio::ip::tcp::resolver::query query("httpbin.org", "http"); boost::asio::ip::tcp::socket socket(io_service); boost::asio::connect(socket, resolver.resolve(query)); boost::beast::http::request req( boost::beast::http::verb::get, "/headers", 11); req.set(boost::beast::http::field::host, "httpbin.org"); req.set(boost::beast::http::field::user_agent, "MyAgent/1"); req.set(boost::beast::http::field::connection, "Close"); write(socket, req); boost::beast::flat_buffer buffer; boost::beast::http::response reply; boost::beast::http::read(socket, buffer, reply); std::cout << reply.body(); }

Ответ 4



Средствами чистого сиплюсплюса можно написать HTTP запрос, используя только iostream. А программу запускать, присоединив streams к netcat. unix-way в чистом виде, если что.

Ответ 5



Можно на чистом с++ это сделать стандартными библиотеками #include или # include . Конечно не ручаюсь, насколько это работает сейчас, но раньше на сокетах как раз можно было написать вполне вменяемы TCP_IP запросы. По первой либе здесь можно посмотреть пример

Комментариев нет:

Отправить комментарий