libcurl: my implementation is slower than native curl - c

I was experimenting with C and libcurl, and noticed that my implementation takes longer than native /usr/bin/curl, while doing a simple HTTPS GET.
Here's my source:
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
/*
#define SKIP_HOSTNAME_VERIFICATION
#define SKIP_PEER_VERIFICATION
*/
int try_url(char *url);
int main(int argc, char **argv){
try_url(argv[1]);
puts("Done");
return 0;
}
int try_url(char *url){
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
#ifdef SKIP_HOSTNAME_VERIFICATION
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
#endif
#ifdef SKIP_PEER_VERIFICATION
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
#endif
res = curl_easy_perform(curl);
if(res != CURLE_OK){
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
Here's the time takes for it to run:
$ time ./a.out "https://dns.google.com/resolve?name=dns.google.com&type=A" 2>/dev/null
{"Status": 0,"TC": false,"RD": true,"RA": true,"AD": false,"CD": false,"Question":[ {"name": "dns.google.com.","type": 1}],"Answer":[ {"name": "dns.google.com.","type": 1,"TTL": 78,"data": "216.58.217.46"}]}Done
real 0m1.038s
user 0m0.746s
sys 0m0.109s
Here's the native curl binary, finishing it in just half the time:
$ time curl -o /dev/null "https://dns.google.com/resolve?name=dns.google.com&type=A" 2>/dev/null
real 0m0.412s
user 0m0.196s
sys 0m0.020s
Could you please point me the right way?
Happens with other urls More info:
$ dpkg -l |egrep "curl|ssl"
ii curl 7.52.1-5+deb9u8 armhf command line tool for transferring data with URL syntax
ii libcurl3:armhf 7.52.1-5+deb9u8 armhf easy-to-use client-side URL transfer library (OpenSSL flavour)
ii libcurl3-gnutls:armhf 7.52.1-5+deb9u9 armhf easy-to-use client-side URL transfer library (GnuTLS flavour)
ii libcurl4-gnutls-dev:armhf 7.52.1-5+deb9u9 armhf development files and documentation for libcurl (GnuTLS flavour)
ii libssl1.0.2:armhf 1.0.2q-1~deb9u1 armhf Secure Sockets Layer toolkit - shared libraries
ii libssl1.1:armhf 1.1.0j-1~deb9u1 armhf Secure Sockets Layer toolkit - shared libraries
ii openssl 1.1.0j-1~deb9u1 armhf Secure Sockets Layer toolkit - cryptographic utility
ldd on my a.out:
$ ldd a.out
linux-vdso.so.1 (0x7eed3000)
/usr/lib/arm-linux-gnueabihf/libarmmem.so (0x76f65000)
libcurl-gnutls.so.4 => /usr/lib/arm-linux-gnueabihf/libcurl-gnutls.so.4 (0x76eeb000)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76dac000)
libnghttp2.so.14 => /usr/lib/arm-linux-gnueabihf/libnghttp2.so.14 (0x76d7e000)
libidn2.so.0 => /usr/lib/arm-linux-gnueabihf/libidn2.so.0 (0x76d4c000)
librtmp.so.1 => /usr/lib/arm-linux-gnueabihf/librtmp.so.1 (0x76d23000)
libssh2.so.1 => /usr/lib/arm-linux-gnueabihf/libssh2.so.1 (0x76cee000)
libpsl.so.5 => /usr/lib/arm-linux-gnueabihf/libpsl.so.5 (0x76cd1000)
libnettle.so.6 => /usr/lib/arm-linux-gnueabihf/libnettle.so.6 (0x76c8a000)
libgnutls.so.30 => /usr/lib/arm-linux-gnueabihf/libgnutls.so.30 (0x76afd000)
libgssapi_krb5.so.2 => /usr/lib/arm-linux-gnueabihf/libgssapi_krb5.so.2 (0x76ab4000)
libkrb5.so.3 => /usr/lib/arm-linux-gnueabihf/libkrb5.so.3 (0x769fd000)
libk5crypto.so.3 => /usr/lib/arm-linux-gnueabihf/libk5crypto.so.3 (0x769be000)
libcom_err.so.2 => /lib/arm-linux-gnueabihf/libcom_err.so.2 (0x769ab000)
liblber-2.4.so.2 => /usr/lib/arm-linux-gnueabihf/liblber-2.4.so.2 (0x7698f000)
libldap_r-2.4.so.2 => /usr/lib/arm-linux-gnueabihf/libldap_r-2.4.so.2 (0x7693a000)
libz.so.1 => /lib/arm-linux-gnueabihf/libz.so.1 (0x76913000)
libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0x768ea000)
/lib/ld-linux-armhf.so.3 (0x76f7b000)
libunistring.so.0 => /usr/lib/arm-linux-gnueabihf/libunistring.so.0 (0x767db000)
libhogweed.so.4 => /usr/lib/arm-linux-gnueabihf/libhogweed.so.4 (0x7679e000)
libgmp.so.10 => /usr/lib/arm-linux-gnueabihf/libgmp.so.10 (0x7672b000)
libgcrypt.so.20 => /lib/arm-linux-gnueabihf/libgcrypt.so.20 (0x7665a000)
libp11-kit.so.0 => /usr/lib/arm-linux-gnueabihf/libp11-kit.so.0 (0x765fa000)
libidn.so.11 => /lib/arm-linux-gnueabihf/libidn.so.11 (0x765b9000)
libtasn1.so.6 => /usr/lib/arm-linux-gnueabihf/libtasn1.so.6 (0x76599000)
libkrb5support.so.0 => /usr/lib/arm-linux-gnueabihf/libkrb5support.so.0 (0x76580000)
libdl.so.2 => /lib/arm-linux-gnueabihf/libdl.so.2 (0x7656d000)
libkeyutils.so.1 => /lib/arm-linux-gnueabihf/libkeyutils.so.1 (0x7655a000)
libresolv.so.2 => /lib/arm-linux-gnueabihf/libresolv.so.2 (0x76535000)
libsasl2.so.2 => /usr/lib/arm-linux-gnueabihf/libsasl2.so.2 (0x7650e000)
libgpg-error.so.0 => /lib/arm-linux-gnueabihf/libgpg-error.so.0 (0x764ee000)
libffi.so.6 => /usr/lib/arm-linux-gnueabihf/libffi.so.6 (0x764d6000)
libgcc_s.so.1 => /lib/arm-linux-gnueabihf/libgcc_s.so.1 (0x764a7000)
Update:
Took out libcurl4-gnutls-dev and installed libcurl4-openssl-dev
498 apt-get remove libcurl4-gnutls-dev
499 apt install libcurl4-openssl-dev
It is behaving much better now:
$ time curl -o /dev/null "https://dns.google.com/resolve?name=dns.google.com&type=A" 2>/dev/null
real 0m0.302s
user 0m0.200s
sys 0m0.020s
$ time ./a.out "https://dns.google.com/resolve?name=dns.google.com&type=A" 2>/dev/null
{"Status": 0,"TC": false,"RD": true,"RA": true,"AD": false,"CD": false,"Question":[ {"name": "dns.google.com.","type": 1}],"Answer":[ {"name": "dns.google.com.","type": 1,"TTL": 299,"data": "216.58.217.46"}],"Comment": "Response from 2001:4860:4802:34::a."}Done
real 0m0.294s
user 0m0.196s
sys 0m0.020s

Related

compiling c language program with libcurl on windows

I am trying to compile a simple c program on windows 10 using gcc from the libcurl website I cloned vcpkg and then ran the .bat file , next I installed curl with the command vcpkg install curl and got this output
Computing installation plan...
The following packages are already installed:
curl[core,non-http,openssl,schannel,ssl,sspi]:x86-windows -> 7.80.0
Package curl:x86-windows is already installed
Restored 0 packages from C:\Users\<me>\AppData\Local\vcpkg\archives in 138.1 us. Use --debug to see more details.
Total elapsed time: 386.9 ms
The package curl provides CMake targets:
find_package(CURL CONFIG REQUIRED)
target_link_libraries(main PRIVATE CURL::libcurl)
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
int report()
{
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://192.168.1.12:8000");
const char* c = const_cast<char*>(output.c_str());
printf ("%s", c);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, c );
/* 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;
}
int main()
{
report();
return 0;
}
Now when I try to compile the code above I get the error
c_example_curl.c:3:23: fatal error: curl/curl.h: No such file or directory
#include <curl/curl.h>
^
compilation terminated.
I am compiling using the command
gcc -lcurl file.c
I also tried using the command
gcc -lcurl -I F:\_C_\vcpkg\installed\x86-windows\include\curl file.c
doesn't seem to change anything
I even tried to copy the curl header file to the working directory of the above code but I was not lucky
How do you install libcurl for windows isn't there any command equivalent to the linux one
download curl for windows here.
unpack the zip and place it anywhere on the system (i personally prefer C:\curl).
then compile your script with: gcc file.c -I<path-to-curl> -L<path-to-curl>\lib -lcurl
NOTE: replace <path-to-curl> with the curl location on the system, for example C:\curl

C - Cmake compiling program with libcurl

I'm trying to use some curl code to test the lib but I can't compile it :(
I'm using Clion (Cmake + gcc) and I've got a libcurl.a, a libcurl.dll and a libcurl.dlla
What am I suppose to do with those 3 files ?
This is my CmakeLists.txt :
cmake_minimum_required(VERSION 3.10)
project(curl_test2 C)
set(CMAKE_C_STANDARD 99)
ADD_DEFINITIONS( -DCURL_STATICLIB )
include_directories( "include" )
set(SRCS"
srcs/main.c")
set(HEADERS
"include/curl/curl.h"
"include/curl/easy.h")
link_directories("lib")
add_executable(curl_test2 ${SRCS} ${HEADERS})
target_link_libraries(curl_test2 "curl")
this is my project:
include
--curl
--curl.h
srcs
--main.c
lib
--libcurl.a
(--dlls
--libcurl.dll
--libcurl.dlla) <- i'm not using them for now
this is my main.c (just a libcurl example, not really important - i'm just trying to compile):
#include <stdio.h>
#include "curl/curl.h"
int main(void)
{
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://postit.example.com/moo.cgi");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=daniel&project=curl");
res = curl_easy_perform(curl);
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
When I'm trying to build the compiler drop this error : "undefined reference to `_imp__curl_global_init'" (and all other curl function calls)
Can you help me ? I'm a bit lost - I did not really use Cmake before..
Thank you !
You link with static curl library (libcurl.a) which required CURL_STATICLIB definition. Add this in your CMakeLists.txt between "project" and "add_executable" commands:
add_definitions( -DCURL_STATICLIB )
Moreover, your file .dlla is not .dll.a ? In that case, .dll.a file is (I think) generated by MinGW toolchain and is required only if you link dynamically with curl library (as .dll file).
I downloaded the sources of cURL library here and compiled it (with Visual Compiler 2015). It produces shared libraries (libcurl.dll and libcurl_imp.lib) that I move in the lib directory (I should rename libcurl_imp.lib to curl.lib). I move also the include directory.
Then, I used this CMakeLists.txt :
cmake_minimum_required(VERSION 3.10)
project(curl_test2 C)
set(CMAKE_C_STANDARD 99)
set(SRCS "srcs/main.c")
set( CURL_LIBRARY ${CMAKE_SOURCE_DIR}/lib )
set( CURL_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include )
find_package( CURL )
include_directories( ${CURL_INCLUDE_DIRS} )
link_directories( ${CURL_LIBRARIES} )
add_executable(curl_test2 ${SRCS})
target_link_libraries(curl_test2 curl)
With it, your project compiles and the execution works.
I also tried with cURL static library (for that, if you use CMake to compile cURL, add -DCURL_STATICLIB=ON in cmake command line). And I moved the produced library libcurl.lib to lib\curl.lib.
I used this CMakeLists.txt :
cmake_minimum_required(VERSION 3.10)
project(curl_test2 C)
set(CMAKE_C_STANDARD 99)
set(SRCS "srcs/main.c")
add_definitions( -DCURL_STATICLIB )
set( CURL_LIBRARY ${CMAKE_SOURCE_DIR}/lib )
set( CURL_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include )
find_package( CURL )
include_directories( ${CURL_INCLUDE_DIRS} )
link_directories( ${CURL_LIBRARIES} )
add_executable(curl_test2 ${SRCS})
target_link_libraries(curl_test2 curl wldap32 ws2_32)
And it works too.

dlopen not finding library that ldconfig -p finds

I'm trying to bind against the CUDA library shared. As a quick verification I wrote the following code:
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *handle;
handle = dlopen ("libcuda.so", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
dlclose(handle);
}
This fails with libcuda.so: cannot open shared object file: No such file or directory.
However, if I check ldconfig I get:
ldconfig -p | grep libcuda
libcuda.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libcuda.so.1
libcuda.so.1 (libc6) => /usr/lib/i386-linux-gnu/libcuda.so.1
libcuda.so (libc6) => /usr/lib/i386-linux-gnu/libcuda.so
So it seems that libcuda.so does exist and is seen by the system. So why is dlopen() failing?
This is on Ubuntu 14.04.
I can see from your ldconfig -p that there is no symlink for libcuda.so.1 x86_64, you just need to create it, try
sudo ln -svf /usr/lib/x86_64-linux-gnu/libcuda.so{.1,}
it might be the case that you don't have the -dev package installed.
Or simply change
handle = dlopen ("libcuda.so", RTLD_LAZY);
to
handle = dlopen ("libcuda.so.1", RTLD_LAZY);
but the first solution is better because when you link dynamically to libcuda.so.1 with -lcuda the symlink migh be mandatory.

Saving a file using libcurl in C

I'm expanding from perl to C and I'm trying to use curl's library to simply save a file from a remote url but I'm having a hard time finding a good example to work from.
Also, I'm not sure if I should be using curl_easy_recv or curl_easy_perform
I find this resource very developer friendly.
I compiled the source code below with:
gcc demo.c -o demo -I/usr/local/include -L/usr/local/lib -lcurl
Basically, it will download a file and save it on your hard disk.
File demo.c
#include <curl/curl.h>
#include <stdio.h>
void get_page(const char* url, const char* file_name)
{
CURL* easyhandle = curl_easy_init();
curl_easy_setopt( easyhandle, CURLOPT_URL, url ) ;
FILE* file = fopen( file_name, "w");
curl_easy_setopt( easyhandle, CURLOPT_WRITEDATA, file) ;
curl_easy_perform( easyhandle );
curl_easy_cleanup( easyhandle );
fclose(file);
}
int main()
{
get_page( "http://blog.stackoverflow.com/wp-content/themes/zimpleza/style.css", "style.css" ) ;
return 0;
}
Also, I believe your question is similar to this one:
Download file using libcurl in C/C++

What's the most efficient way to get source code of web page in C?

In PHP I can do it as simple as :
file_get_contents('http://stackoverflow.com/questions/ask');
What's the shortest code to do the same in C?
UPDATE
When I compile the sample with curl, got errors like this:
unresolved external symbol __imp__curl_easy_cleanup referenced in function _main
Use libcurl, refer to their example C snippets
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
Try the libcurl C interface
I should have commented the Richard Harrison good answer, but I have not 50 reputations points yet, so I put here as an answer my hint to ieplugin for compiling the code:
On Ubuntu 10.04 (and supposing you named the source file getpage.c):
sudo apt-get install libcurl4-dev
gcc getpage.c -lcurl -o getpage

Resources