LibCurl库&HTTP操作

LibCurl库&HTTP操作



任务摘要

. 学习LibCurl库,编程练习:
1)基本的http GET/POST操作;
2)获取html网页、网页下载保存;
3)文件的断点续传;


一、libcurl简介

libcurl是什么
libcurl是一个跨平台的网络协议库,支持http, https, ftp, gopher, telnet, dict, file, ldap协议等。
libcurl同样支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传, HTTP基本表单上传,代理,cookies,用户认证等。
libcurl基本函数
CURLcode curl_global_init(long flags)
这个函数只能用一次。
void curl_global_cleanup(void)
在结束libcurl使用的时候,用来对curl_global_init做的工作清理。类似于clean。
har *curl_version( )
打印当前libcurl库的版本。
CURL *curl_easy_init( )
用来初始化一个CURL的指针, 相应的在调用结束时要用curl_easy_cleanup函数清理。
void curl_easy_cleanup(CURL *handle);
用来结束一个会话。
CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
用于告诉curl库程序将有如何的行为。

二、基本的http GET/POST操作

代码

#include <stdio.h>
#include <curl/curl.h>
bool getUrl(char *filename)
{
    
    
    CURL *curl;
    CURLcode res;
    FILE *fp;
    if ((fp = fopen(filename, "w")) == NULL)  // 返回结果用文件存储
        return false;
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "Accept: Agent-007");
    curl = curl_easy_init();    // 初始化
    if (curl)
    {
    
    
        //curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");// 代理
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);// 改协议头
        curl_easy_setopt(curl, CURLOPT_URL,"http://www.baidu.com");
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); //将返回的http头输出到fp指向的文件
        curl_easy_setopt(curl, CURLOPT_HEADERDATA, fp); //将返回的html主体数据输出到fp指向的文件
        res = curl_easy_perform(curl);   // 执行
        if (res != 0) {
    
    

            curl_slist_free_all(headers);
            curl_easy_cleanup(curl);
        }
        fclose(fp);
        return true;
    }
}
bool postUrl(char *filename)
{
    
    
    CURL *curl;
    CURLcode res;
    FILE *fp;
    if ((fp = fopen(filename, "w")) == NULL)
        return false;
    curl = curl_easy_init();
    if (curl)
    {
    
    
        curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookie.txt"); // 指定cookie文件
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "&logintype=uid&u=xieyan&psw=xxx86");    // 指定post内容
        //curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");
        curl_easy_setopt(curl, CURLOPT_URL, " http://mail.sina.com.cn/cgi-bin/login.cgi ");   // 指定url
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);
    }
    fclose(fp);
    return true;
}
int main(void)
{
    
    
    getUrl("/tmp/get.html");
    postUrl("/tmp/post.html");
}

编译

gcc get_post.c -o get_post –curl

在这里插入图片描述
解决方式

gcc get_post.c -o get_post

在这里插入图片描述
代码中的bool修改成int,false修改为0,true修改为1
在这里插入图片描述
编译语句修改

gcc get_post.c -o get_post –curl

运行

./get_post

在这里插入图片描述

三、获取html网页、网页下载保存

获取html网页
代码

#include <stdio.h>
#include <curl/curl.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    
    
    CURL *curl;             //定义CURL类型的指针
CURLcode res;           //定义CURLcode类型的变量,保存返回状态码
    if(argc!=2)
    {
    
    
        printf("Usage : file <url>;\n");
        exit(1);
    }
 
    curl = curl_easy_init();        //初始化一个CURL类型的指针
    if(curl!=NULL)
    {
    
    
        //设置curl选项. 其中CURLOPT_URL是让用户指 定url. argv[1]中存放的命令行传进来的网址
        curl_easy_setopt(curl, CURLOPT_URL, argv[1]);        
        //调用curl_easy_perform 执行我们的设置.并进行相关的操作. 在这 里只在屏幕上显示出来.
        res = curl_easy_perform(curl);
        //清除curl操作.
        curl_easy_cleanup(curl);
    }
    return 0;
}

编译

gcc get_html.c -o get_html -lcurl

运行

./get_html http://www.baidu.com

在这里插入图片描述
网页下载保存
代码

// 采用CURLOPT_WRITEFUNCTION 实现网页下载保存功能
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
#include <curl/curl.h>
//#include <curl/types.h>
#include <curl/easy.h>
 
FILE *fp;  //定义FILE类型指针
//这个函数是为了符合CURLOPT_WRITEFUNCTION而构造的
//完成数据保存功能
size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)  
{
    
    
    int written = fwrite(ptr, size, nmemb, (FILE *)fp);
    return written;
}
 
int main(int argc, char *argv[])
{
    
    
    CURL *curl;
 
    curl_global_init(CURL_GLOBAL_ALL);  
    curl=curl_easy_init();
    curl_easy_setopt(curl, CURLOPT_URL, argv[1]);  
 
    if((fp=fopen(argv[2],"w"))==NULL)
    {
    
    
        curl_easy_cleanup(curl);
        exit(1);
    }
//CURLOPT_WRITEFUNCTION 将后继的动作交给write_data函数处理
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);  
    curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    exit(0);
}

编译

gcc save_html.c -o save_html -lcurl

运行

./save_html http://www.baidu.com ./baidu

在这里插入图片描述

四、断点续传

代码

//采用CURLOPT_RESUME_FROM_LARGE 实现文件断点续传功能
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
 
#include <curl/curl.h>
//这个函数为CURLOPT_HEADERFUNCTION参数构造
/* 从http头部获取文件size*/
size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void *stream) {
    
    
       int r;
       long len = 0;
 
       /* _snscanf() is Win32 specific */
       // r = _snscanf(ptr, size * nmemb, "Content-Length: %ld\n", &len);
 r = sscanf(ptr, "Content-Length: %ld\n", &len);
       if (r) /* Microsoft: we don't read the specs */
              *((long *) stream) = len;
 
       return size * nmemb;
}
 
/* 保存下载文件 */
size_t wirtefunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
        return fwrite(ptr, size, nmemb, stream);
}
 
/*读取上传文件 */
size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
       FILE *f = stream;
       size_t n;
 
       if (ferror(f))
              return CURL_READFUNC_ABORT;
 
       n = fread(ptr, size, nmemb, f) * size;
 
       return n;
}
 
// 下载 或者上传文件函数
int download(CURL *curlhandle, const char * remotepath, const char * localpath,
           long timeout, long tries)
{
    
    
       FILE *f;
       curl_off_t local_file_len = -1 ;
       long filesize =0 ;
       
       CURLcode r = CURLE_GOT_NOTHING;
       int c;
  struct stat file_info;
  int use_resume = 0;
  /* 得到本地文件大小 */
  //if(access(localpath,F_OK) ==0)
  
    if(stat(localpath, &file_info) == 0) 
     {
    
    
        local_file_len =  file_info.st_size;
        use_resume  = 1;
      }
  //采用追加方式打开文件,便于实现文件断点续传工作
       f = fopen(localpath, "ab+"); 
       if (f == NULL) {
    
    
              perror(NULL);
              return 0;
       }
 
       //curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, 1L);
 
       curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath);
 
              curl_easy_setopt(curlhandle, CURLOPT_CONNECTTIMEOUT, timeout);  // 设置连接超时,单位秒
       //设置http 头部处理函数
       curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getcontentlengthfunc);
       curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &filesize);
 // 设置文件续传的位置给libcurl
       curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM_LARGE, use_resume?local_file_len:0);
 
       curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, f);
       curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, wirtefunc);
 
       //curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, readfunc);
       //curl_easy_setopt(curlhandle, CURLOPT_READDATA, f);
       curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 1L);
       curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);
  
  
  r = curl_easy_perform(curlhandle);
       
 
       fclose(f);
 
       if (r == CURLE_OK)
              return 1;
       else {
    
    
              fprintf(stderr, "%s\n", curl_easy_strerror(r));
              return 0;
       }
}
 
int main(int c, char **argv) {
    
    
       CURL *curlhandle = NULL;
 
       curl_global_init(CURL_GLOBAL_ALL);
       curlhandle = curl_easy_init();
 
       //download(curlhandle, "ftp://user:pass@host/path/file", "C:\\file", 0, 3);
  download(curlhandle , "https://sunlight-dazzling.github.io/file/introduce.txt","./index.asp",1,3);
       curl_easy_cleanup(curlhandle);
       curl_global_cleanup();
 
       return 0;
}

编译

gcc resume.c -o resume -lcurl

运行

./resume

在这里插入图片描述
当前目录下可以看到对应下载的文件。


五、总结

通过几个实际例子,可以清楚看出libcurl在获取http网址的网页信息上,是比较方便的。断点续传指的是将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,当碰到网络故障,可以从已经上传或下载的部分开始继续上传下载未完成的部分,而没有必要从头开始上传下载。这可以节省用户时间。

六、参考资料

C++ 用libcurl库进行http通讯网络编程.

猜你喜欢

转载自blog.csdn.net/QWERTYzxw/article/details/112253616