cURL 是一个网络数据传输项目,通常说 cURL 是指 curl 命令行工具,它支持 DICT、FILE、FTP、FTPS、Gopher、HTTP、HTTPS、IMAP、IMAPS、LDAP、LDAPS、POP3、POP3S、RTMP、RTSP、SCP、SFTP、SMB、SMBS、SMTP、SMTPS、Telnet 与 TFTP 等协议,而 curl 的底层使用的是 libcurl 库,libcurl 与 curl 组成了 cURL 项目。
curl 源码下载 https://curl.se/download.html
下载之后三步:
1.解压
2.进入目录:./configure --with-gnutls (打开tls)
3.make
4.make install
测试命令:
curl -v https://www.baidu.com
curl -V
命令没问题的话我们源码编译安装成功,下面就可以写代码实现了。
https实现下载功能:
#include
#include
#include
#include
static int download_progress;
struct progress {
char *private;
size_t size;
};
typedef struct HTTP_OPT
{
char url[128]; /*url of https*/
// char *user_key; // username:password
char *file; /*filepath*/
}HTTP_OPT;
static size_t callback_download_response(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
int count = 0;
FILE* fp = (FILE *)userp;
if (!fp) {
/* out of memory! */
fprintf(stderr ,"not file to save download data .\n");
return 0;
}
if(contents && realsize > 0 ) {
count = fwrite(contents, 1, realsize, fp);
if (count != realsize) {
fprintf(stderr, "write file failed, size:%d != write_count:%d\n", realsize, count);
fflush(fp);
return 0;
}
}
fflush(fp);
return realsize;
}
static size_t progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
{
int progress = 0;
progress = (int)(dlnow / dltotal * 100);
fprintf(stderr, "download progress = %d / 100", progress);
download_progress = progress;
return 0;
}
int get_download_progress()
{
return download_progress;
}
CURL *curl_init() //curl初始化
{
download_progress = 0;
curl_global_init(CURL_GLOBAL_DEFAULT);
CURL *curl = curl_easy_init();
if(NULL == curl)
{
fprintf(stderr, "Init curl failed.\n");
exit(1);
}
return curl;
}
void curl_deinit(CURL *curl) //退出curl
{
curl_easy_cleanup(curl);
curl_global_cleanup();
}
int https_download(const HTTP_OPT http_option)
{
CURL *curl;
struct progress data;
FILE *fp = fopen(http_option.file, "w");
if(NULL == fp)
{
fprintf(stderr, "Open file failed at %s:%d\n", __FILE__, __LINE__);
return -1;
}
curl = curl_init();
if (curl) {
CURLcode res;
curl_easy_setopt(curl, CURLOPT_POST, 0);
curl_easy_setopt(curl, CURLOPT_URL, http_option.url);
//跳过证书校验
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
//6秒未达到30字节会退出
curl_easy_setopt(curl,CURLOPT_LOW_SPEED_TIME,6L);
curl_easy_setopt(curl,CURLOPT_LOW_SPEED_LIMIT,30L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback_download_response);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
//获得进度条
// curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &data);
// curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
// curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
//res = curl_easy_getinfo(curl, CURLINFO_HTTP_CODE);
res = -1;
}
fclose(fp);
curl_deinit(curl);
return 0;
}
return -1;
}
int download_https(char* addr, char* refile, char* lofile)
{
HTTP_OPT http_opt;
sprintf(http_opt.url, "%s%s", addr, refile);
fprintf(stderr, "http_opt.url = %s\n",http_opt.url);
http_opt.file = lofile;
if (https_download(http_opt) != 0) {
fprintf(stderr, "Download failed.\n");
return -1;
} else {
fprintf(stderr, "Download success.\n");
return 0;
}
}
int main()
{
download_https("https://filesamples.com","/samples/image/bmp/sample_640×426.bmp", "sample_640×426.bmp" );
}
ftp实现下载功能
#include
#include
#include
#include
#include
#include
#include
#include
typedef enum FTP_STATE
{
FTP_UPLOAD_SUCCESS,
FTP_UPLOAD_FAILED,
FTP_DOWNLOAD_SUCCESS,
FTP_DOWNLOAD_FAILED
}FTP_STATE;
typedef struct FTP_OPT
{
//char *url; /*url of ftp*/
char url[80]; /*url of ftp*/
char *user_key; /*username:password*/
char *file; /*filepath*/
}FTP_OPT;
char _ip_addr[16];//远程主机IP地址
static int get_file_size(FILE *file) //获取文件大小
{
int size = 0;
fseek(file, 0L, SEEK_END);
size = ftell(file);
fseek(file, 0L, SEEK_SET);
return size;
}
static int getipaddr(const char* _host)
{
memset(_ip_addr, 0, 16);
/*通过域名得到相应的ip地址*/
struct hostent *host = gethostbyname(_host);//此函数将会访问DNS服务器
if (!host) {
fprintf(stderr, "找不到IP地址,请检查DNS服务器!");
return(-1);
}
for (int i = 0; host->h_addr_list[i]; i++) {
strcpy(_ip_addr, inet_ntoa( * (struct in_addr*) host->h_addr_list[i]));
break;
}
if (strlen(_ip_addr) == 0) {
fprintf(stderr, "错误: 无法获取到远程服务器的IP地址, 请检查下载地址的有效性\n");
return(-1);
}
return 0;
}
CURL *curl_init() //curl初始化
{
curl_global_init(CURL_GLOBAL_DEFAULT);
CURL *curl = curl_easy_init();
if(NULL == curl)
{
fprintf(stderr, "Init curl failed.\n");
exit(1);
}
return curl;
}
void curl_set_upload_opt(CURL *curl, const char *url, const char *user_key, FILE *file) //设置上传配置参数
{
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_USERPWD, user_key);
curl_easy_setopt(curl, CURLOPT_READDATA, file);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
curl_easy_setopt(curl, CURLOPT_INFILESIZE, get_file_size(file));
curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, 1);
// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
}
void curl_set_download_opt(CURL *curl, const char *url, const char *user_key, FILE *file) //设置下载配置参数
{
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_USERPWD, user_key);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
}
void curl_exit(CURL *curl) //退出curl
{
curl_easy_cleanup(curl);
curl_global_cleanup();
}
CURLcode curl_perform(CURL *curl) //执行curl
{
CURLcode ret = curl_easy_perform(curl);
if(ret != 0)
{
fprintf(stderr, "Perform curl failed.\n");
curl_exit(curl);
exit(1);
}
return ret;
}
FTP_STATE ftp_upload(const FTP_OPT ftp_option) //ftp上传文件
{
FTP_STATE state;
CURL *curl;;
FILE *fp = fopen(ftp_option.file, "r");
if(NULL == fp)
{
fprintf(stderr, "Open file failed at %s:%d\n", __FILE__, __LINE__);
return FTP_UPLOAD_FAILED;
}
curl = curl_init();
curl_set_upload_opt(curl, ftp_option.url, ftp_option.user_key, fp);
if(CURLE_OK == curl_perform(curl))
state = FTP_UPLOAD_SUCCESS;
else
state = FTP_UPLOAD_FAILED;
curl_exit(curl);
fclose(fp);
return state;
}
FTP_STATE ftp_download(const FTP_OPT ftp_option) // ftp下载文件
{
FTP_STATE state;
CURL *curl;
FILE *fp = fopen(ftp_option.file, "w");
if(NULL == fp)
{
fprintf(stderr, "Open file failed at %s:%d\n", __FILE__, __LINE__);
return FTP_UPLOAD_FAILED;
}
curl = curl_init();
curl_set_download_opt(curl, ftp_option.url, ftp_option.user_key, fp);
if(CURLE_OK == curl_perform(curl))
state = FTP_DOWNLOAD_SUCCESS;
else
state = FTP_DOWNLOAD_FAILED;
curl_exit(curl);
fclose(fp);
return state;
}
int download_ftp(char* addr, char* refile, char* lofile)
{
if(getipaddr(addr) < 0)
return -1;
FTP_OPT ftp_opt;
sprintf(ftp_opt.url, "ftp://%s%s", _ip_addr, refile);
fprintf(stderr, "ftp_opt.url = %s\n",ftp_opt.url);
ftp_opt.file = lofile; //指下载到本地文件名
ftp_opt.user_key = "anonymous:";
if(FTP_DOWNLOAD_SUCCESS == ftp_download(ftp_opt))
fprintf(stderr, "Download success.\n");
else
fprintf(stderr, "Download failed.\n");
return 0;
}
int main()
{
download_ftp("192.168.5.3","/samples/image/bmp/sample_640×426.bmp", "sample_640×426.bmp" );
}