问题描述
//...
CURL *curl;
FILE *fp;
CURLcode res;
char outfilename[FILENAME_MAX] = "file";
curl = curl_easy_init();
/* no progress meter please */
//curl_easy_setopt(curl,CURLOPT_nopROGRESS,1L);
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_data);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,&sharedValue);
curl_easy_setopt(curl,CURLOPT_READFUNCTION,read_data);
curl_easy_setopt(curl,CURLOPT_READDATA,CURLOPT_OPENSOCKETFUNCTION,opensocket);
curl_easy_setopt(curl,CURLOPT_OPENSOCKETDATA,CURLOPT_CLOSESOCKETFUNCTION,closecb);
curl_easy_setopt(curl,CURLOPT_CLOSESOCKETDATA,CURLOPT_URL,hostname.c_str());
curl_easy_setopt(curl,CURLOPT_SOCKOPTFUNCTION,sockopt_callback);
curl_easy_setopt(curl,CURLOPT_VERBOSE,1);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
我不知道该怎么处理CURLOPT_SOCKOPTFUNCTION
,所以我做了sockopt_callback
,
static curl_socket_t opensocket(void *clientp,curlsocktype purpose,struct curl_sockaddr *address)
{
return 0;
}
但是我明白了
* Trying 212.183.159.230:80...
* Could not set TCP_NODELAY: Socket operation on non-socket
* connect to 212.183.159.230 port 80 Failed: Socket operation on non-socket
libcurl wants to close 0 Now
因为可能正在尝试写入套接字0
。显然,我不能阻止它调用套接字上的选项,例如设置TCP_NODELAY
和最重要的connect
。
我的一个想法是传递一个现有的套接字作为libcurl的虚拟对象,然后仍然使用我的写入和读取功能。但是,libcurl只是通过套接字发送内容,而不是通过write和read函数发送
解决方法
我以为write_data
是重定向套接字调用的一种方法,但它与它无关,它实际上是一个写客户端收到的内容的函数。
但是,通过传递一个socketpair
(如@domen表示的那样),我使它起作用了!
素描:
//...
static curl_socket_t opensocket(void *clientp,curlsocktype purpose,struct curl_sockaddr *address)
{
auto *sharedValue = static_cast<SharedValue *>(clientp);
return sharedValue->curl_socket;
}
int socket_vector[2];
if (0 != socketpair(AF_UNIX,SOCK_STREAM,socket_vector))
{
std::cout << "problem creating socketpair" << std::endl;
std::exit(2);
}
sharedValue.curl_socket = socket_vector[0];
sharedValue.vpn_socket = socket_vector[1];
//writes the result to a file
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_data_file);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,destFile);
curl_easy_setopt(curl,CURLOPT_OPENSOCKETFUNCTION,opensocket);
curl_easy_setopt(curl,CURLOPT_OPENSOCKETDATA,&sharedValue);
curl_easy_setopt(curl,CURLOPT_CLOSESOCKETFUNCTION,closecb);
curl_easy_setopt(curl,CURLOPT_CLOSESOCKETDATA,CURLOPT_SOCKOPTFUNCTION,sockopt_callback);
curl_easy_setopt(curl,CURLOPT_URL,hostname.c_str());
//curl_easy_setopt(curl,CURLOPT_VERBOSE,1);
//Start a thread here that will read/write to the socket pair on the other endpoint (in my case vpn_socket)
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if (res)
{
std::cout << "libcurl error code: " << res << ",libcurl error: " << curl_easy_strerror(res) << std::endl;
return 1;
}