使用C ++ / boost :: asio / libcurl的简单代理 - 无法下载图像 [英] Simple proxy using C++/boost::asio/libcurl - can't download images
问题描述
我试图使用下面的代码实现一个非常简单的代理服务器。您将浏览器的代理设置为192.168.1.x:8080,并通过代理访问网页。
I'm trying to implement a very simple proxy server with the following code. You set your browser's proxy to 192.168.1.x:8080 and web pages are accessible through the proxy.
#include <ctime>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include <boost/algorithm/string.hpp>
#include <curl/curl.h>
#include <cstdlib>
using boost::asio::ip::tcp;
int port=8080;
//CURL *curl;
//CURLcode res;
static size_t write_to_string(void *ptr, size_t size, size_t count, void *stream) {
((std::string*)stream)->append((char*)ptr, 0, size*count);
return size*count;
}
class session{
public:
session(boost::asio::io_service& io_service):socket_(io_service){
}
tcp::socket &socket(){
return socket_;
}
void start(){
socket_.async_read_some(boost::asio::buffer(data_,max_length),boost::bind(&session::handle_read,this,boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
}
private:
void handle_read(const boost::system::error_code& error,size_t bytes_transferred){
CURL *curl;
CURLcode res;
std::string response;
std::string errorBuffer[CURL_ERROR_SIZE];
std::string host="";
std::string url="";
if(!error){
//boost::asio::async_write(socket_,boost::asio::buffer(data_,bytes_transferred),boost::bind(&session::handle_write,this,boost::asio::placeholders::error));
printf("%s",data_);
//parse data_:
//std::string host="";
//std::string url="";
std::vector<std::string> split1;
boost::split(split1, data_, boost::is_any_of("\r\n"));
std::vector<std::string> split2;
boost::split(split2,split1.at(0),boost::is_any_of(" "));
std::cout<<"***"<<split2.at(0)<<"***"<<std::endl;
if(split2.at(0).compare("GET")==0){
printf("Get request recieved\n");
url=split2.at(1);
int i=0;
for(i=1;i<split1.size();i++){
if(split1.at(i).compare("Host:")>0){
std::cout<<split1.at(i)<<std::endl;
std::vector<std::string> split3;
boost::split(split3,split1.at(i),boost::is_any_of(" "));
std::cout<<split3.at(1)<<std::endl;
host=split3.at(1);
break;
}
}
}
//trim host to remove \r\n
host.erase(host.find_last_not_of(" \n\r\t")+1);
url.erase(url.find_last_not_of(" \n\r\t")+1);
//std::string response;
//std::string errorBuffer[CURL_ERROR_SIZE];
//CURL *curl;
//CURLcode res;
curl=curl_easy_init();
if(curl){
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_HEADER, 0);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_ENCODING, "gzip");
//curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookies.txt");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_to_string);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
std::cout<<errorBuffer<<std::endl;
//curl_easy_setopt(curl,CURLOPT_URL,url.c_str());
//curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_to_string);
//curl_easy_setopt(curl,CURLOPT_WRITEDATA,&response);
res=curl_easy_perform(curl);
std::cout<<">>>"<<res<<std::endl;
curl_easy_cleanup(curl);
std::cout<<response<<std::endl;
boost::asio::async_write(socket_,boost::asio::buffer(response,response.length()),boost::bind(&session::handle_write,this,boost::asio::placeholders::error));
//curl_free(curl);
}else{
printf("Error: curl can't be init'd");
}
}else{
printf("***handle_read: Error***\n");
std::cout<<error<<std::endl;
std::cout<<"EOH:"<<res<<std::endl;
std::cout<<url<<std::endl;
std::cout<<"EOH:"<<errorBuffer<<std::endl;
delete this;
}
}
void handle_write(const boost::system::error_code& error){
if (!error){
socket_.async_read_some(boost::asio::buffer(data_, max_length),boost::bind(&session::handle_read, this,boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
socket_.cancel();
}else{
printf("***handle_write: Error***");
std::cout<<error<<std::endl;
delete this;
}
}
tcp::socket socket_;
enum { max_length = 1000000 };
char data_[max_length];
};
class server
{
public:
server(boost::asio::io_service& io_service, short port): io_service_(io_service),acceptor_(io_service,tcp::endpoint(tcp::v4(), port)){
start_accept();
}
private:
void start_accept(){
session* new_session = new session(io_service_);
acceptor_.async_accept(new_session->socket(),boost::bind(&server::handle_accept, this, new_session,boost::asio::placeholders::error));
}
void handle_accept(session* new_session,const boost::system::error_code& error){
if (!error){
new_session->start();
}else{
delete new_session;
}
start_accept();
}
boost::asio::io_service& io_service_;
tcp::acceptor acceptor_;
};
int main(){
try{
boost::asio::io_service io_service;
//tcp_server write(io_service);
server read(io_service,port);
io_service.run();
}
catch (std::exception& e){
std::cerr << e.what() << std::endl;
}
return 0;
}
使用 g ++ proxy.c -lboost_system -lcurl
我遇到的麻烦是图片不会下载!所有其他texty文件(html,js,css)下载正常,只是图像不会出现。
The trouble I'm having is that images won't download! All other texty files (html, js, css) download fine, it's just images won't appear.
任何人都可以给我任何建议吗?我真的卡住了。我正在考虑将curl切换成某种二进制模式。当我cout包含图像的字符串,它似乎打印到sdtout罚款(我可以看到PNG头)。但是当我尝试写这个文件到套接字,它不是在浏览器中出现的某种原因,我不能到达底部。
Can anyone give me any suggestions? I'm really stuck now. I was thinking about switching curl into some sort of "binary mode". When I cout the string that contains the image, it seems to print to sdtout fine (I can see the "PNG" header). But when I try to write this file to the socket, it's not coming up in the browser for some reason I cannot get to the bottom of.
在@Tomalak Geret'kal的推荐,我现在使用curlpp
On recommendation of @Tomalak Geret'kal, I'm now using curlpp
curlpp::Cleanup myCleanup;
curlpp::Easy myRequest;
myRequest.setOpt<cURLpp::Options::Url>(url);
std::ostringstream os;
curlpp::options::WriteStream ws(&os);
myRequest.setOpt(ws);
myRequest.perform();
os << myRequest;
boost::asio::async_write(socket_,boost::asio::buffer(xxx,xxx.length())),boost::bind(&session::handle_write,this,boost::asio::placeholders::error));
<我不确定要转换 os
到为了它与async_write ...
My question now is, how do I write using async_write? I'm not sure what to convert os
to in order for it to be compatible with async_write...
推荐答案
就像将服务器响应(std :: string)转换为png文件 ,您使用 std :: string
错误。
例如,以下代码:
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
假设& response
到字符数组或缓冲区。但它不是:它是一个指向 std :: string
的指针,它是一个具有实现定义内部结构的复杂对象。
assumes that &response
is a pointer to a character array or buffer. However, it's not: it's a pointer to an std::string
, a complex object with implementation-defined internals.
您应该使用其定义明确的API,请参阅此推荐阅读材料列表中的收藏夹。
You should use its well-defined API instead, referring to your favourite from this list of recommended reading material.
您会发现使用此 C风格 cURL API和 std :: string
不是完全直观的。为什么不使用 C ++绑定,cURLpp ?
You will find that working with this C-style cURL API and std::string
is not entirely intuitive. Why not use the C++ binding, cURLpp?
这篇关于使用C ++ / boost :: asio / libcurl的简单代理 - 无法下载图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!