多线程的libcurl的使用
摘要:libcurl在多线程中,采用https访问,经常运行一段时间,会出现crash。
libcurl的在多线程中的使用特别注意的有两点:
1. curl的句柄不能多线程共享。
2. ssl访问时, openssl是线程不安全的。
知道了这两点,就能解决libcurl无故crash的问题了。
第一点:每个线程初始化一个句柄,供这个线程使用。
第二点:需要添加回调函数,进行线程锁。
参考代码如下:
#include <stdio.h>
#include <pthread.h>
#include <curl/curl.h> #define NUMT 4 /* we have this global to let the callback get easy access to it */
static pthread_mutex_t *lockarray; #ifdef USE_OPENSSL
#include <openssl/crypto.h>
static void lock_callback(int mode, int type, char *file, int line)
{
(void)file;
(void)line;
if(mode & CRYPTO_LOCK) {
pthread_mutex_lock(&(lockarray[type]));
}
else {
pthread_mutex_unlock(&(lockarray[type]));
}
} static unsigned long thread_id(void)
{
unsigned long ret; ret = (unsigned long)pthread_self();
return ret;
} static void init_locks(void)
{
int i;
printf("crypto num is %d\r\n", CRYPTO_num_locks());
lockarray = (pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
sizeof(pthread_mutex_t));
for(i = 0; i<CRYPTO_num_locks(); i++) {
pthread_mutex_init(&(lockarray[i]), NULL);
} CRYPTO_set_id_callback((unsigned long (*)())thread_id);
CRYPTO_set_locking_callback((void (*)())lock_callback);
} static void kill_locks(void)
{
int i; CRYPTO_set_locking_callback(NULL);
for(i = 0; i<CRYPTO_num_locks(); i++)
pthread_mutex_destroy(&(lockarray[i])); OPENSSL_free(lockarray);
} /* List of URLs to fetch.*/
const char * const urls[]= {
"https://www.example.com/",
"https://www2.example.com/",
"https://www3.example.com/",
"https://www4.example.com/",
}; static void *pull_one_url(void *url)
{
CURL *curl; curl = curl_easy_init();//每个线程初始化一个句柄,绝对不能混用。
curl_easy_setopt(curl, CURLOPT_URL, url);
/* this example doesn't verify the server's certificate, which means we
might be downloading stuff from an impostor */
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_perform(curl); /* ignores error */
curl_easy_cleanup(curl); return NULL;
} int main(int argc, char **argv)
{
pthread_t tid[NUMT];
int i;
(void)argc; /* we don't use any arguments in this example */
(void)argv; /* Must initialize libcurl before any threads are started */
curl_global_init(CURL_GLOBAL_ALL); init_locks();//初始化openssl的回调函数,加载线程锁 for(i = 0; i< NUMT; i++) {
int error = pthread_create(&tid[i],
NULL, /* default attributes please */
pull_one_url,
(void *)urls[i]);
if(0 != error)
fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
else
fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]);
} /* now wait for all threads to terminate */ for(i = 0; i< NUMT; i++) {
pthread_join(tid[i], NULL);
fprintf(stderr, "Thread %d terminated\n", i);
} kill_locks();//销毁openssl线程锁 return 0;
}
多线程的libcurl的使用的更多相关文章
- 多线程使用libcurl
curl默认情况下有两个地方是线程不安全的, 需要特殊处理, 1是curl_global_init 这个函数必须单线程调用, 2是默认多线程调用https会莫名其妙的挂掉, 以下是网上的解决方案 ht ...
- VC使用libcurl模拟登录CSDN并自动评论资源以获取积分
环境:Win7 64位+VC2008 软件及源码下载:(http://pan.baidu.com/s/1jGE52pK) 涉及到的知识点: C++多线程编程 libcurl的使用(包括发送http请求 ...
- libcurl模拟登录CSDN并自动评论资源以获取积分
软件及源码下载:(http://pan.baidu.com/s/1jGE52pK) 涉及到的知识点: C++多线程编程 libcurl的使用(包括发送http请求.发送cookie给服务器.保存coo ...
- curl raise 信号出core
在使用c++多线程使用libcurl抓取网页时,遇到程序随机core掉的情况,gdb 一下出错信息有这么一条:longjmp causes uninitialized stack frame. 在网上 ...
- Libcurl多线程crash问题(cento)
cento :http://blog.csdn.net/delphiwcdj/article/details/18284429 1 问题背景 后台系统有一个单线程的http接口,为了提高并发处理能力, ...
- libcurl多线程超时设置不安全(转)
from http://www.cnblogs.com/kex1n/p/4135263.html (1), 超时(timeout) libcurl 是 一个很不错的库,支持http,ftp等很多的协议 ...
- libcurl的封装,支持同步异步请求,支持多线程下载,支持https
最近在做一个项目,需要用到http get post等 需求分析需要做到同步和异步,异步请求的返回以可选的回调通知的方式进行. 本人以Linux为例,一步一步的来实现. 配置并且编译libcurl我以 ...
- libcurl 多线程使用注意事项 - Balder~专栏 - 博客频道 - CSDN.NET
libcurl 多线程使用注意事项 - Balder~专栏 - 博客频道 - CSDN.NET libcurl 多线程使用注意事项 分类: C/C++学习 2012-05-24 18:48 2843人 ...
- HTTP多线程下载+断点续传(libcurl库)
目录索引: 一.LibCurl基本编程框架 二.一些基本的函数 三.curl_easy_setopt函数部分选项介绍 四.curl_easy_perform 函数说明(error 状态码) 五.lib ...
随机推荐
- CF792A New Bus Route 题解
Content 给定一个长度为 \(n\) 的数列 \(a_1,a_2,a_3,...,a_n\),求这个序列当中差的绝对值最小的数对并求出这样的数对的个数. 数据范围:\(2\leqslant n\ ...
- LuoguP7714 「EZEC-10」排列排序 题解
Content 给定一个 \(1\sim n\) 的一个排列 \(p\),你每次可以选择一个区间 \([l,r]\) 并花费 \(r-l+1\) 的代价将下标在这个区间内的所有数升序排序,求使得排列 ...
- response 返回js的alert()语句,中文乱码如何解决
response 返回js的alert()语句,中文乱码如何解决, 步骤1:在后台加上如下代码: response.setCharacterEncoding("utf-8"); r ...
- Qt之QListView和QStandardItemModel用法
note 个人理解, QListView 用于 显示数据,而数据的逻辑维护则由 QStandardItemModel 完成. QStandardItemModel 创建 if (nullptr == ...
- Windows c(++)获取磁盘剩余容量
头文件 #include <windows.h> #include <wtypes.h> 函数 GetDiskFreeSpaceExA 获取剩余可用空间 /// 得到盘符, 例 ...
- iOS越狱插件源查找及避免插件劫持
1.关于 iOS越狱插件源查找地址:https://www.ios-repo-updates.com/ 2.注意 不要使用不可靠的第三方源,其可能存在劫持,而你却茫然不知. 使用上面的网站查找你需要的 ...
- 【LeetCode】716. Max Stack 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 双栈 日期 题目地址:https://leetcode ...
- python学习第三天:python基础(数据类型和变量)
注释 以 # 开头的语句是注释,如,注释不会被编译运行: 格式 当语句以冒号:结尾时,缩进的语句视为代码块.按照约定俗成的管理,应该始终坚持使用4个空格的缩进(在文本编辑器中,需要设置把Tab自动转 ...
- Mysql客户端的安装
Mysql数据库(简称)属于C/S架构,正常工作中一般都会提供服务端,我们只需要安装客户端进行查询修改数据等操作即可. 正常工作中不管是测试人员或者开发人员,一般数据库的管理员(测试负责人或者开发负责 ...
- 计算机系统2->从芯片说起 | 芯片怎样诞生
这部分数字逻辑课上老师在讲CMOS部分时有讲过,当时在课堂上放了一个全英的视频,没怎么看懂,现在在研究计算机系统,自底层说起,也得从这讲起. 主要参考: <嵌入式C语言自我素养> b站相关 ...