libcurl 开源库 —— 提供多种数据传输功能(FTP, HTTP,HTTPS,FTPS,TELNET等)的函数库 - Go语言中文社区

libcurl 开源库 —— 提供多种数据传输功能(FTP, HTTP,HTTPS,FTPS,TELNET等)的函数库


你不知道的 libcurl

ibcurl是一个提供数据传输功能的函数库,主要功能就是通过其使用不同的协议连接不同类型的服务器。当前libcurl支持的协议主要有http, https, ftp, gopher, telnet, dict, file, 和ldap等协议和各种SSL安全认证。

在基于libcurl的程序里,使用libcurl提供的库函数完成特定任务。开发者在启动传输任务之前写好回调函数以及设置各类参数,当满足条件时,libcurl调用回调函数实现功能任务。
当然,官网上有其详细的介绍:
https://curl.haxx.se/libcurl/features.html

你还需要知道的 libcurl

实现逻辑

在这里插入图片描述

函数说明

a) CURLcode curl_global_init(long falgs);

该函数在程序中只能够使用一次,若这个函数在curl_easy_init函数调用时还没调用,它将由libcurl库自动完成。该函数需要用到的参数如下:

CURL_GLOBAL_ALL:初始化所有可能的调用

CURL_GLOBAL_SSL:初始化支持安全套接字的调用

CURL_GLOBAL_WIN32:初始化WIN32套接字库

CURL_GLOBAL_NOTHING:没有额外的初始化要求

b) CURL* curl_easy_init();

用来初始化一个curl指针。在该指针调用结束后需要使用curl_easy_cleanup函数清理。
通常来说当使用curl_easy_init()产生一个curl指针后,基本上只会被curl库中easy系列函数中调用。

c) CURLcode curl_easy_setopt(CURL* handle,CURLoption option,parameter);

用来告诉curl库程序需要该库做何等行为。CURL* handle为操作符,CURLoption option代表各类选项,option parameter 这个参数既可以是个函数的指针,也可以是某个对象的指针,也可以是个long型的变量.它用什么这取决于第二个参数.。

d) CURLcode curl_easy_perform(CURL* handle);

设置好curl_easy_setopt工作方式后,调用该函数开始运行会话。CURL* handle为操作符。

e) void curl_easy_cleanup(CURL*handle);

用来结束一个libcurl会话,与curl_easy_init配合使用。CURL* handle为操作符。

f) void curl_global_cleanup(void);

用该函数结束所有有关libcurl使用,类似于close()的函数。

要是对libcur库中所有函数进行一个详细的了解,可以参考libcurl官网:
https://curl.haxx.se/libcurl/c/

让它(libcurl) 为你所用(以使用FTPS通讯功能为例)

搭建FTPS服务器,使用vsftpd 来搭建,使用FileZilla进行测试

FTPS是什么?FTPS是一种对常用的文件传输协议(FTP)添加传输层安全(TLS)和安全套接层(SSL)加密协议支持的扩展协议。
通过vsftpd搭建ftps服务器步骤:

1 apt-get install vsftpd
2 service vsftpd restart
3 然后就可以直接访问该服务地址了
4 实现支持SSL加密传输的ftp服务器
a) 配置颁发证书的根机构

        1) 修改openssl 的 CA 默认路径,vi /etc/ssl/openssl.cnf
        2)  在 /ect/ssl/ 下创建 demoCA : mkdir demoCA
        3)  在/etc/ssl/demoCA 下执行 :  mkdir crl certs newcerts
        4)  在/etc/ssl/demoCA 下执行 :  touch index.txt serial //新建相应的文件和目录 
        5) 在/etc/ssl/demoCA 下执行 : echo "01">serial //证书的序列号从1开始
        6) 在/etc/ssl/demoCA 下执行 : mkdir private
        7)  在/etc/ssl/demoCA 下执行 : openssl genrsa 1024 >private/cakey.pem    //产生私钥
        8) 在/etc/ssl/demoCA 下执行 : chmod 600 private/*      //更改权限
        9) openssl req -new -key private/cakey.pem -x509 -out cacert.pem -days 3650 //产生证书

b) 为FTP申请证书

   1) mkdir /etc/vsftpd/certs  //创建存放私有钥匙,证书等信息的目录
   2) openssl genrsa 1024 >vsftpd.key  //产生秘钥
   3) openssl req -new -key vsftpd.key -out vsftpd.csr   //产生证书
   4) openssl ca -in vsftpd.csr -out vsftpd.cert  //向根机构申请证书
   5) chmod 600 *     //更改存放证书私钥的目录权限
   6)  vi /etc/vsftpd.conf  //修改配置文件
    ##启动ssl,并支持ssl的版本
    ssl_enable=YES
    ssl_tlsv1=YES
    ssl_sslv3=YES
    ssl_sslv2=YES
    allow_anon_ssl=NO
    force_local_logins_ssl=YES
    force_local_data_ssl=YES
    ##指定证书和钥匙的目录
     rsa_cert_file=/etc/vsftpd/certs/vsftpd.cert
    rsa_private_key_file=/etc/vsftpd/certs/vsftpd.key
    ps: common name 直接填IP或者域名
  1. 测试,

    1) 安装FileZilla 客户端软件
    2) 打开软件,创建站点,按如下配置后点击连接
    3) 证书出来后,点击确认:

将libcurl + openssl 进行交叉编译,在编译libcurl前需要先编译openssl,有依赖关系

  1. 下载资源包:
    Libcurl库 下载地址:
    https://github.com/curl/curl.git
    Openssl库下载地址: http://distfiles.macports.org/openssl/
    我下载了 openssl-1.0.2a
  2. 交叉编译openssl
    a) 将openssl-1.0.2a 解压到 服务器下
    b) 在 ./openssl-1.0.2a/下 创建tmp目录,mkdir tmp
    c) 执行 ./Configure --cross-compile-prefix=aarch64-himix100-linux- no-asm no-hw shared --openssldir=/data2/zhengxiaoyu/work/source/openssl-1.0.2a/tmp linux-elf
    d) Make
    e) Make install
    f) 在./tmp/ 下生成编译后的文件
  3. 交叉编译 libcurl
    a) curl-master 解压到服务器下
    b) 在 ./ curl-master /下 创建tmp目录,mkdir tmp
    c) 执行 ./configure --prefix=/data2/zhengxiaoyu/work/source/curl-master/tmp --host=aarch64-himix100-linux --target=aarch64-himix100-linux -with-ssl=/data2/zhengxiaoyu/work/source/openssl-1.0.2a/tmp
    需要开启ssl 功能,默认是关闭,=openssl 依赖库路径
    d) Make –j4
    e) Make install
    f) 在./tmp/ 下生成编译后的文件

配置与测试,需要将服务器证书和上传下载路径准备好

a) 挂载nfs,
b) 挂载成功后,将可执行文件ftpdownload 和 ftps服务器的证书cacert.pem copy 到nfs 下

写测试demo

  1. 静态库测试
    a) Copy libcrypto.a and libssl.a 到 ./tmp/lib 下
    b) 写好测试代码,将代码copy 到./tmp/下
    c) 执行 linux-gcc ftpdownload.c -o ftpdownload -lcurl -lssl -lcrypto -pthread -ldl -L./lib -I./include –static 生成可执行文件ftpdownload
    e) 执行 ./ftpdownload ,就可以从服务器上下载文件,/nfs/ 下就可以看到一个curl.txt文件
    测试代码:
    upload
#include <stdio.h>
#include <string.h
#include <curl/curl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#ifdef WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

#define LOCAL_FILE      "/home/MyProject/ftp_test/test_file/uploadthis.txt" //要上传的文件
#define UPLOAD_FILE_AS  "while-uploading.txt"
#define REMOTE_URL      "ftp://127.0.0.1/MyFtpServerPath/"  UPLOAD_FILE_AS //FTP服务器地址
#define RENAME_FILE_TO  "renamed-and-fine.txt"
#define FTP_USER_PWD    "hahaha:123456"

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
  curl_off_t nread;

  size_t retcode = fread(ptr, size, nmemb, stream);

  nread = (curl_off_t)retcode;

  fprintf(stderr, " We read %" CURL_FORMAT_CURL_OFF_T
          " bytes from filen", nread);
  return retcode;
}

int main(void)
{
  CURL *curl;
  CURLcode res;
  FILE *hd_src;
  struct stat file_info;
  curl_off_t fsize;

  struct curl_slist *headerlist = NULL;
  static const char buf_1 [] = "RNFR " UPLOAD_FILE_AS;
  static const char buf_2 [] = "RNTO " RENAME_FILE_TO;

  /* 获得上传文件的大小 */ 
  if(stat(LOCAL_FILE, &file_info)) {
    printf("Couldn't open '%s': %sn", LOCAL_FILE, strerror(errno));
    return 1;
  }
  fsize = (curl_off_t)file_info.st_size;

  printf("Local file size: %" CURL_FORMAT_CURL_OFF_T " bytes.n", fsize);

  /* 获得FILE类型变量 */ 
  hd_src = fopen(LOCAL_FILE, "rb");

  /* 初始化 */ 
  curl_global_init(CURL_GLOBAL_ALL);

  /* 获得curl操作符 */ 
  curl = curl_easy_init();
  if(curl) {
    /*建立一个传递给libcurl的命令列表 */ 
    headerlist = curl_slist_append(headerlist, buf_1);
    headerlist = curl_slist_append(headerlist, buf_2);

    /* 使用curl提供的Read功能 */ 
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);

    /* 上传使能 */ 
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);

    /* 设置特定目标 */ 
    curl_easy_setopt(curl, CURLOPT_URL, REMOTE_URL);

	 /* 设置账号密码 */ 
    curl_easy_setopt(curl, CURLOPT_USERPWD, FTP_USER_PWD);
	
    /* 传递最后一个FTP命令以在传输后运行 */ 
    curl_easy_setopt(curl, CURLOPT_POSTQUOTE, headerlist);

    /*指定上传文件 */ 
    curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);

    /*设置要上传的文件的大小(可选) */ 
    curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
                     (curl_off_t)fsize);
					 
	/* We activate SSL and we require it for both control and data */ 
    curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
	
	curl_easy_setopt(curl, CURLOPT_CAINFO, "/etc/ssl/demoCA/cacert.pem");  
    /* 运行 */ 
    res = curl_easy_perform(curl);
    /* 容错处理 */ 
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %sn",
              curl_easy_strerror(res));

    /* 清除FTP命令列表 */ 
    curl_slist_free_all(headerlist);

    /*释放所有curl资源 */ 
    curl_easy_cleanup(curl);
  }
  fclose(hd_src); /*关闭本地文件 */ 

  /*释放所有curl资源 */ 
  curl_global_cleanup();
  return 0;
}

download

#include <stdio.h>
#include <curl/curl.h>

#define FTP_USER_PWD    "hahaha:123456"

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 && !out->stream) {
    /* 打开文件以进行写操作 */ 
    out->stream = fopen(out->filename, "wb");
    if(!out->stream)
      return -1; /* failure, can't open file to write */ 
  }
  return fwrite(buffer, size, nmemb, out->stream);
}


int main(void)
{
  CURL *curl;
  CURLcode res;
  struct FtpFile ftpfile = {
    "curl.txt", /* 若FTP下载成功,名命下载后的文件为"curl.txt" */ 
    NULL
  };

  curl_global_init(CURL_GLOBAL_DEFAULT);

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL,
                     "ftp://127.0.0.1/MyFtpServerPath/a.txt");//下载指定的文件
	
	/* 设置账号密码 */ 
    curl_easy_setopt(curl, CURLOPT_USERPWD, FTP_USER_PWD);
	
    /* 定义回调函数,以便在需要写入数据时进行调用 */ 
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
	
    /*设置一个指向我们的结构的指针传递给回调函数*/ 
    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);
	
	//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);  
	//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
	curl_easy_setopt(curl, CURLOPT_CAINFO, "/etc/ssl/demoCA/cacert.pem");  
    //curl_easy_setopt(curl,CURLOPT_SSLCERT,“client.pem”);
    //curl_easy_setopt(curl,CURLOPT_SSLKEY,“key.pem”);
    //curl_easy_setopt(curl,CURLOPT_KEYPASSWD,“s3cret”);
	
	/* 打开完整的协议/调试输出*/ 
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

    res = curl_easy_perform(curl);

    /* 释放所有curl资源*/ 
    curl_easy_cleanup(curl);

    if(CURLE_OK != res) {
      /*容错处理 */ 
      fprintf(stderr, "curl told us %dn", res);
    }
  }

  if(ftpfile.stream)
    fclose(ftpfile.stream); /* 关闭本地文件 */ 
 /*释放所有curl资源*/
  curl_global_cleanup();

  return 0;
}

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/black_yu/article/details/97550363
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢