When I'm trying to connect to a new url I need to run the program with the new url, the program fails to connect and when I restart the program it will connect.
So what I'm trying to do is reset, all connections and instead of restarting the program just try to connect to the url once and then reset the connection and reconnecting, causing the same effect as restarting the program.
Is there any way to do that? And what causes my program to not load a new url? And forcing me to restart the program to make it work?
Here is my code:
#include <iostream>
#include <curl/curl.h>
#include <string>
#include <fstream>
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
int main(void)
{
std::ofstream file("source.txt");
CURL *curl;
CURLcode res = CURL_LAST;
std::string readBuffer;
curl = curl_easy_init();
while (curl && res != CURLE_OK){
curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.com/");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if (res != CURLE_OK)
curl = curl_easy_init();
}
file << readBuffer;
file.close();
std::cout << readBuffer << std::endl;
std::cin.ignore();
return 0;
}
Here I'm trying to use a while loop to reconnect and trying to use curl_easy_init() to reset the connection
Related
I have a curl script:
curl -k -H "Content-Type: application/txt" -X POST --data-binary "#name_file.txt" -g "https://ya.com/file.txt" > .\out.txt
I can use it via console ant it works good.
I implement this script in visual studio on C++:
auto curl = curl_easy_init();
if (curl)
{
FILE* fp = fopen(path_to_file.c_str(), "wb");
curl_easy_setopt(curl, CURLOPT_URL, "https://ya.com/file.txt");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
struct curl_slist *list = NULL;
list = curl_slist_append(list, "Content-Type: application/txt");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); // - H
std::string data_for_send = data_for_send_arr.c_str();
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data_for_send.size());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data_for_send.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callbackfunction);
res = curl_easy_perform(curl);
if (res != CURLE_OK) AfxMessageBox(_T("error"));
curl_easy_cleanup(curl);
curl_global_cleanup();
fclose(fp);
}
size_t callbackfunction(void *ptr, size_t size, size_t nmemb, void* userdata)
{
FILE* stream = (FILE*)userdata;
if (!stream)
{
printf("!!! No stream\n");
return 0;
}
size_t written = fwrite((FILE*)ptr, size, nmemb, stream);
return written;
}
i also i need to tell that at one moment i use async call:
async(func_curl_1, data_1);
async(func_curl_2, data_2);
each function create curl and do request for server at the same time.
but this script do not work. it work one time from seven request
server returned for me empty file or broken file.
i do not know why...
try to add in your settings CURLOPT_VERBOSE
i.e.
/* ask libcurl to show us the verbose output */
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
and investigate output
I tried compiling both the examples on this question: Download file using libcurl in C/C++
Here's one of them:
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
FILE *fp;
CURLcode res;
char *url = "http://stackoverflow.com";
char outfilename[FILENAME_MAX] = "page.html";
curl = curl_easy_init();
if (curl)
{
fp = fopen(outfilename,"wb");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
fclose(fp);
}
return 0;
}
the problem is that this example, when run, immediately returns and I get a blank file. Why? I modified to
if (curl)
{
fp = fopen(outfilename,"wb");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
fclose(fp);
} else {
printf("error\n");
}
but I see no error. I tried compiling in both C++ and C, I get the same result on both.
I had the same issue and I fixed it by:
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true);
According to https://curl.se/libcurl/c/CURLOPT_FOLLOWLOCATION.html, true tells the library to follow HTTP location.
I am trying trying to make a POST request on a url with protobuf data. I don't know how/ where to add binary data. Below is my C++ program.
"
void sendContent()
{
using namespace std;
int Error = 0;
//CString str;
CURL* curl;
CURLcode res;
struct curl_slist *headerlist = NULL;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
headerlist = curl_slist_append(headerlist, "Content-Type: application/x-protobuf");
//Set URL to recevie POST
curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
curl_easy_setopt(curl, CURLOPT_POST, true);
curl_easy_setopt(curl, CURLOPT_HEADER, true);
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:9090/info");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_global_cleanup();
}"
You should set the data pointer by curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);. In the meantime, you should set the data size by curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, length_of_data);.
You can find the libcurl post example in there.
And I copy the program below.
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if(curl) {
/* First set the URL that is about to receive our POST. This URL can
just as well be a https:// URL if that is what should receive the
data. */
curl_easy_setopt(curl, CURLOPT_URL, "http://postit.example.com/moo.cgi");
/* Now specify the POST data */
/* size of the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, length_of_data);
/* binary data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
Fixing your original suggestion would probably make it something like this (based on the simplepost example from the libcurl web site):
#include <curl/curl.h>
int binarypost(char *binaryptr, long binarysize)
{
CURL *curl;
CURLcode res = CURLE_OK;
struct curl_slist *headerlist = NULL;
headerlist = curl_slist_append(headerlist, "Content-Type: application/x-protobuf");
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:9090/info");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, binaryptr);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, binarysize);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return (int)res;
}
I'm trying to download remote html pages with my C++ program, however with some URLs a timeout occurs, but I don't know how to handle this, so the program will just hang indefinatly.
virtual void downloadpage(string pageaddress) {
CURL *curl;
CURLcode informationdownloaded;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13");
curl_easy_setopt(curl, CURLOPT_URL, pageaddress.c_str());
curl_easy_setopt(curl, CURLOPT_HEADER, 0);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writepageinformation);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &pageinformation);
informationdownloaded = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
}
Here is my function for downloading the html source of a page into a string variable called "pageinformation" via the "writepageinformation" function.
informationdownloaded = curl_easy_perform(curl);
You can also specify timeout for your download
curl_easy_setopt(hCurl, CURLOPT_TIMEOUT, iTimeoutSeconds); // timeout for the URL to download
This is a blocked call until the entire file is downloaded.
If you are interested to interrupt the blocked call (for signal to kill) install a progress callback, like below
curl_easy_setopt(hCurl, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(hCurl, CURLOPT_PROGRESSFUNCTION, progress_callback);
curl_easy_setopt(hCurl, CURLOPT_PROGRESSDATA, this);
static int progress_callback(void *clientp,
double dltotal,
double dlnow,
double ultotal,
double ulnow)
{
CLASS &obj = *(CLASS*)clientp;
if (obj.exit)
return 1; // if u want the signal curl to unblock and return from curl_easy_perform
return 0; // if u want the callback to continue
}
Use the CURLOPT_TIMEOUT option?
Use the CURLOPT_PROGRESSFUNCTION callback and make the operation stop whenever you think it is enough?
Use the CURLOPT_LOWSPEED option or similar to make it depend on transfer rate.
Along with other suggestions to use CURLOPT_TIMEOUT which will enable you to define a timeout, you should just check for the return value of curl_easy_perform as it's a blocking call. Here is a slightly modified version of doc/examples/getinfo.c of libcurl,
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
int main(int argc, char* argv[])
{
CURL *curl;
CURLcode res;
if (argc != 2) {
printf("Usage: %s <timeoutInMs>\n", argv[0]);
return 1;
}
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/ip");
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, atol(argv[1]));
res = curl_easy_perform(curl);
if (CURLE_OK == res)
printf("Success.\n");
else if (CURLE_OPERATION_TIMEDOUT == res)
printf("Operation timed out.\n");
curl_easy_cleanup(curl);
return 0;
}
i got a small program from http://curl.haxx.se/ and while i run it always prints the webpage how can i disable the printing function
#include <iostream>
#include <curl/curl.h>
using namespace std;
int main() {
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://google.com");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,1);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
You need to set up a CURLOPT_WRITEFUNCTION to make it not use stdout.
There is an explanation here (under CURLOPT_WRITEFUNCTION):
http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
and here (Under "Handling the Easy libcurl):
http://curl.haxx.se/libcurl/c/libcurl-tutorial.html
Basically adding the function:
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp)
{
return size * nmemb;
}
and calling
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
Should do it.
You can still get diagnostic messages. To stop these either change or add the following line:
curl_easy_setopt (curl, CURLOPT_VERBOSE, 0L); //0 disable messages
To write data into file instead of printing, give a file descriptor as:
FILE *wfd = fopen("foo.txt", "w");
...
curl_easy_setopt(curl, CURLOPT_WRITEDATA, wfd);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
What worked for me was using the CURLOPT_NOBODY option in the code, referenced here: http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTNOBODY
#include <iostream>
#include <curl/curl.h>
using namespace std;
int main() {
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://google.com");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,1);
//USING CURLOPT NOBODY
curl_easy_setopt(curl, CURLOPT_NOBODY,1);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}