libcurl 使用教程

libcurl使用教程

最近一个项目,使用libcurl来做HTTP CLIENT服务,踩了不少坑,特别分享一下这些坑。

我使用的是libcurl的同步接口,支持openssl,多线程环境。

1、环境初始化

    使用libcurl时,首先要初始化libcurl的运行环境,退出应用时,也要清理环境。

    应用加载时:curl_global_init(CURL_GLOBAL_ALL);

    应用退出时:curl_global_cleanup();

   

2、多线程

    多线程支持,每一个线程保持一个libcurl的句柄。这个很重要。不要混用,否则程序会出现莫名的crash。直接上线程代码。

    

static void* voice_thread_func(void* data) {
 
   CURL* curl1;
   curl1 = curl_easy_init();
 
   wz_recog_channel_t* recog_channel = (wz_recog_channel_t*)(data);
   while(1)  {
       pthread_mutex_lock(&recog_channel->mt);
       if (recog_channel->stop != 0) {
         apt_log(RECOG_LOG_MARK, APT_PRIO_INFO, "asr voice thread exit");
         pthread_mutex_unlock(&recog_channel->mt);
         curl_easy_cleanup(curl1);
         return;
       }
       pthread_mutex_unlock(&recog_channel->mt);
       //apt_log(RECOG_LOG_MARK, APT_PRIO_INFO,"TOTAL:%d
",recog_channel->total_size);
       pthread_mutex_lock(&recog_channel->buffer_read_mt);
       int tmp_size = recog_channel->buffer_read + chunk_size;
       if (tmp_size > recog_channel->total_size) {
          pthread_mutex_unlock(&recog_channel->buffer_read_mt);
          usleep(10000);
          continue;
       }
       long current_pos = recog_channel->buffer_read;
       recog_channel->buffer_read += chunk_size;
       long seq = recog_channel->seq;
       recog_channel->seq++;
       pthread_mutex_unlock(&recog_channel->buffer_read_mt);
       apt_log(RECOG_LOG_MARK, APT_PRIO_INFO, "current_pos %d, seq %d, buffer_read %d, total_size %d",current_pos, seq, recog_channel->buffer_read, recog_channel->tota     l_size);
       send_voice_asr(recog_channel, current_pos, seq, curl1);
   } 
 }
View Code

3、https支持

   证书机制,设置证书的位置,加载。

curl_easy_setopt(curl1, CURLOPT_SSL_VERIFYPEER,0);
curl_easy_setopt(curl1, CURLOPT_SSL_VERIFYHOST,0);
curl_easy_setopt(curl1, CURLOPT_SSLCERTTYPE,"PEM");
curl_easy_setopt(curl1, CURLOPT_SSLCERT, "client.pem");
curl_easy_setopt(curl1, CURLOPT_SSLKEY, "key.pem");

4、坑

    如果多线程一定设置NOSIGAL,

    curl_easy_setopt(curl1, CURLOPT_NOSIGNAL, 1L);

    OPENSSL  连接异常会出现crash,后来检查发现是因为failf的故障日志导致的。这个bug找了好久。查找了 openssl.c才知道原因。

   

 if(SSL_CTX_use_certificate_chain_file(ctx,
 cert_file) != 1) {
 failf(data,
 "could not load PEM client certificate, " OSSL_PACKAGE
 " error %s, "
 "(no key found, wrong pass phrase, or wrong file format?)",
 ossl_strerror(ERR_get_error(), error_buffer,
 sizeof(error_buffer)) );
 return 0;
}

    

   

    

深圳麦集思科技有限公司
原文地址:https://www.cnblogs.com/damizhou/p/14685128.html