根据百度百科的解释:CURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行。它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具。cURL还包含了用于程序开发的libcurl。
cURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行。它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具。cURL还包含了用于程序开发的libcurl。
cURL支持的通信协议有FTP、FTPS、HTTP、HTTPS、TFTP、SFTP、Gopher、SCP、Telnet、DICT、FILE、LDAP、LDAPS、IMAP、POP3、SMTP和RTSP。
curl还支持SSL认证、HTTP POST、HTTP PUT、FTP上传, HTTP form based upload、proxies、HTTP/2、cookies、用户名+密码认证(Basic, Plain, Digest, CRAM-MD5, NTLM, Negotiate and Kerberos)、file transfer resume、proxy tunneling。
系统环境:
下载curl
下载后,解压:
配置
./configure --prefix=/home/caozilong/Workspace/curl/install --with-openssl
编译
执行make进行编译:
安装
make install,安装进INSTALL目录:
基于libcurl开发下载应用
/*
demo_curl.c
curl demo : 结合 lbcurl example 下的ftpsget.c progressfunc.c
实现下载网络文件,下载进度显示,断点下载
*/
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include <stdio.h>
#include <sys/stat.h>
#include <curl/curl.h>
/* <DESC>
* Get a single file from an FTPS server.
* </DESC>
*/
struct FtpFile {
const char *filename;
FILE *stream;
};
static size_t my_fwrite(void *buffer, size_t size, size_t nmemb,
void *stream)
{
struct FtpFile *out = (struct FtpFile *)stream;
if(!out->stream) {
/* open file for writing */
out->stream = fopen(out->filename, "ab+");
if(!out->stream)
return -1; /* failure, can't open file to write */
}
return fwrite(buffer, size, nmemb, out->stream);
}
struct myprogress {
curl_off_t lastruntime; /* type depends on version, see above */
CURL *curl;
};
/* this is how the CURLOPT_XFERINFOFUNCTION callback works */
static int xferinfo(void *p,
curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow)
{
struct myprogress *myp = (struct myprogress *)p;
CURL *curl = myp->curl;
curl_off_t curtime = 0;
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &curtime);
/* under certain circumstances it may be desirable for certain functionality
to only run every N seconds, in order to do this the transaction time can
be used */
if((curtime - myp->lastruntime) >= 3000000) {
myp->lastruntime = curtime;
fprintf(stderr, "TOTAL TIME: %" CURL_FORMAT_CURL_OFF_T ".%06ld\r\n",
(curtime / 1000000), (long)(curtime % 1000000));
}
fprintf(stderr, "UP: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
" DOWN: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
"\r\n",
ulnow, ultotal, dlnow, dltotal);
return 0;
}
int main(void)
{
CURL *curl;
CURLcode res;
struct FtpFile ftpfile = {
"yourfile.bin", /* name to store the file as if successful */
NULL
};
struct myprogress prog;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
/*
* You better replace the URL with one that works! Note that we use an
* FTP:// URL with standard explicit FTPS. You can also do FTPS:// URLs if
* you want to do the rarer kind of transfers: implicit.
*/
curl_easy_setopt(curl, CURLOPT_URL,
"https://curl.se/download/curl-7.83.1.tar.gz");
curl_off_t local_file_len = -1;
struct stat file_info;
int use_resume = 0;
if(stat(ftpfile.filename , &file_info) == 0)
{
local_file_len = file_info.st_size;
use_resume = 1;
}
/* resuming upload at this position, possibly beyond 2GB */
curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, use_resume?local_file_len:0);
/* Define our callback to get called when there's data to be written */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
/* Set a pointer to our struct to pass to the callback */
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
/* We activate SSL and we require it for both control and data */
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
/* Switch on full protocol/debug output */
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
prog.lastruntime = 0;
prog.curl = curl;
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, xferinfo);
/* pass the struct pointer into the progress function */
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
if(CURLE_OK != res) {
/* we failed */
fprintf(stderr, "curl told us %d\n", res);
}
}
if(ftpfile.stream)
fclose(ftpfile.stream); /* close the local file */
curl_global_cleanup();
return 0;
}
编译应用
gcc -I ../install/include/ -L ../install/lib/ main.c -lcurl
将下载的yourfile.bin和curl-7.83.1.tar.gz对比,二者完全一致。
经过调试,程序是双线程程序,但是进度打印是在主线程中完成的
断点续传的原理:
检查文件是否存在,如果存在,说明是之前下载过一部分,没有下载完成,这个时候设置use_resume FLAG,并且调用CURLOPT_RESUME_FROM_LARGE来设置断点续传模式:
CURL具备更多的SSL支持
curl可以使用十个不同的SSL/TLS库之一来构建,它可以提供更多控制权并更广泛地支持协议详细信息。
测试用例
编译测试:
make test