找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 128|回复: 4

CURL网络访问 多线程无法正常取到返回

[复制链接]

2

主题

4

回帖

38

积分

新手上路

积分
38
发表于 2025-1-2 11:54:15 | 显示全部楼层 |阅读模式


单线程情况下正常,多线程取不到返回内容

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×

66

主题

280

回帖

1277

积分

管理员

积分
1277
发表于 2025-1-3 13:59:29 | 显示全部楼层
是不是 不支持多线程

2

主题

4

回帖

38

积分

新手上路

积分
38
 楼主| 发表于 2025-1-3 15:18:12 | 显示全部楼层
admin 发表于 2025-1-3 13:59
是不是 不支持多线程

对,测过了,多线程跑不了,多线程下 只有最后一个会正常发送请求,按照网上例子,改了下初始化和清理,能跑多线程了,不太懂C,不知道会不会有其他问题
  1. #include "module_curl2.h"
  2. #include <mutex>  // 用于std::mutex

  3. // 静态互斥锁,保护全局curl初始化和清理
  4. static std::mutex curl_global_mutex;

  5. CURL网络传输类2::CURL网络传输类2()
  6. {
  7.     m_RequstHeaderList = NULL;
  8.     m_curl = NULL;
  9.     m_form = NULL;
  10. }

  11. size_t CURL网络传输类2::write_data(void* contents, size_t size, size_t nmemb, void* userp)
  12. {
  13.     size_t realsize = size * nmemb;
  14.     struct MemoryStruct* mem = (struct MemoryStruct*)userp;

  15.     char* ptr = (char*)realloc(mem->memory, mem->size + realsize + 1);
  16.     if (ptr == NULL) {
  17.         /* out of memory! */
  18.         printf("not enough memory (realloc returned NULL)\n");
  19.         return 0;
  20.     }

  21.     mem->memory = ptr;
  22.     memcpy(&(mem->memory[mem->size]), contents, realsize);
  23.     mem->size += realsize;
  24.     mem->memory[mem->size] = 0;

  25.     return realsize;
  26. }

  27. size_t CURL网络传输类2::write_head(char* buffer, size_t size, size_t nitems, void* userp)
  28. {
  29.     size_t realsize = size * nitems;
  30.     struct MemoryStruct* mem = (struct MemoryStruct*)userp;

  31.     char* ptr = (char*)realloc(mem->memory, mem->size + realsize + 1);
  32.     if (ptr == NULL) {
  33.         /* out of memory! */
  34.         printf("not enough memory (realloc returned NULL)\n");
  35.         return 0;
  36.     }

  37.     mem->memory = ptr;
  38.     memcpy(&(mem->memory[mem->size]), buffer, realsize);
  39.     mem->size += realsize;
  40.     mem->memory[mem->size] = 0;

  41.     return realsize;
  42. }

  43. int CURL网络传输类2::全局初始化CURL() {
  44.     std::lock_guard<std::mutex> lock(curl_global_mutex);
  45.     static bool is_initialized = false;
  46.     if (!is_initialized) {
  47.         CURLcode ret = curl_global_init(CURL_GLOBAL_ALL);
  48.         if (ret != CURLE_OK) {
  49.             return (vint)ret;
  50.         }
  51.         is_initialized = true;
  52.     }
  53.     return CURLE_OK;
  54. }

  55. char* CURL网络传输类2::取版本() {
  56.     char* ver = curl_version();
  57.     return ver;
  58. }

  59. CURL* CURL网络传输类2::初始化CURL句柄() {
  60.     ZeroMemory(m_szErrorBuffer, sizeof(m_szErrorBuffer));
  61.     m_curl = curl_easy_init();
  62.    
  63.     // 每个线程使用独立的内存结构
  64.     m_ResponsBody.memory = (char*)malloc(1);
  65.     if (m_ResponsBody.memory != NULL) m_ResponsBody.memory[0] = (char)0;
  66.     m_ResponsBody.size = 0;

  67.     curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, write_data);
  68.     curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, (void*)&m_ResponsBody);

  69.     m_ResponsHead.memory = (char*)malloc(1);
  70.     if (m_ResponsHead.memory != NULL) m_ResponsHead.memory[0] = (char)0;
  71.     m_ResponsHead.size = 0;

  72.     curl_easy_setopt(m_curl, CURLOPT_HEADERFUNCTION, write_head);
  73.     curl_easy_setopt(m_curl, CURLOPT_HEADERDATA, (void*)&m_ResponsHead);

  74.     m_RequstHeaderList = NULL;
  75.     curl_easy_setopt(m_curl, CURLOPT_ERRORBUFFER, m_szErrorBuffer);

  76.     return m_curl;
  77. }

  78. void CURL网络传输类2::置地址(LPCSTR url) {
  79.     curl_easy_setopt(m_curl, CURLOPT_URL, url);
  80. }

  81. void CURL网络传输类2::置代理(LPCSTR proxy) {
  82.     curl_easy_setopt(m_curl, CURLOPT_PROXY, proxy);
  83. }

  84. void CURL网络传输类2::置文件(LPCSTR name, LPCSTR file) {
  85.     struct curl_httppost* lastptr = NULL;
  86.     curl_formadd(&m_form, &lastptr,
  87.                      CURLFORM_COPYNAME, name,
  88.                      CURLFORM_FILE, file,
  89.                      CURLFORM_END);
  90.     curl_easy_setopt(m_curl, CURLOPT_HTTPPOST, m_form);
  91. }

  92. void CURL网络传输类2::置POST数据(const char* data, long length)
  93. {
  94.     curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, data);
  95.     curl_easy_setopt(m_curl, CURLOPT_POSTFIELDSIZE, length);
  96. }

  97. BOOL CURL网络传输类2::执行访问()
  98. {
  99.     if (m_RequstHeaderList != NULL) {
  100.         curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_RequstHeaderList);
  101.     }

  102.     if (m_ResponsHead.memory != NULL)
  103.     {
  104.         free(m_ResponsHead.memory);
  105.     }

  106.     if (m_ResponsBody.memory != NULL)
  107.     {
  108.         free(m_ResponsBody.memory);
  109.     }

  110.     // 每个线程使用独立的内存结构
  111.     m_ResponsBody.memory = (char*)malloc(1);
  112.     if (m_ResponsBody.memory != NULL) m_ResponsBody.memory[0] = (char)0;
  113.     m_ResponsBody.size = 0;

  114.     m_ResponsHead.memory = (char*)malloc(1);
  115.     if (m_ResponsHead.memory != NULL) m_ResponsHead.memory[0] = (char)0;
  116.     m_ResponsHead.size = 0;

  117.     BOOL res = (curl_easy_perform(m_curl) == CURLE_OK) ? TRUE : FALSE;
  118.     return res;
  119. }

  120. void CURL网络传输类2::清理() {
  121.     curl_easy_cleanup(m_curl);
  122.     curl_formfree(m_form);

  123.     if (m_ResponsHead.memory != NULL)
  124.     {
  125.         free(m_ResponsHead.memory);
  126.     }
  127.     if (m_ResponsBody.memory != NULL)  
  128.     {
  129.         free(m_ResponsBody.memory);
  130.     }
  131. }

  132. void CURL网络传输类2::置UserAgent(LPCSTR m_UserAgent)
  133. {
  134.     if (m_curl == NULL) {
  135.         return;
  136.     }
  137.     curl_easy_setopt(m_curl, CURLOPT_USERAGENT, m_UserAgent);
  138. }

  139. void CURL网络传输类2::置Encoding(LPCSTR m_Encoding)
  140. {
  141.     if (m_curl == NULL) {
  142.         return;
  143.     }
  144.     curl_easy_setopt(m_curl, CURLOPT_ACCEPT_ENCODING, m_Encoding);
  145. }

  146. void CURL网络传输类2::置Referer(LPCSTR m_Referer)
  147. {
  148.     if (m_curl == NULL) {
  149.         return;
  150.     }
  151.     curl_easy_setopt(m_curl, CURLOPT_REFERER, m_Referer);
  152. }

  153. void CURL网络传输类2::置TimeOut(INT m_TimeOut)
  154. {
  155.     if (m_curl == NULL) {
  156.         return;
  157.     }
  158.     curl_easy_setopt(m_curl, CURLOPT_NOSIGNAL, true); //libcurl支持毫秒, 用户反馈需要开启这个才支持毫秒
  159.     curl_easy_setopt(m_curl, CURLOPT_CONNECTTIMEOUT_MS, m_TimeOut);
  160. }

  161. void CURL网络传输类2::置Nobody()
  162. {
  163.     curl_easy_setopt(m_curl, CURLOPT_NOBODY);
  164. }

  165. void CURL网络传输类2::置请求头(LPCSTR header)
  166. {
  167.     m_RequstHeaderList = curl_slist_append(m_RequstHeaderList, header);
  168. }

  169. void CURL网络传输类2::清空请求头()
  170. {
  171.     curl_slist_free_all(m_RequstHeaderList);
  172.     m_RequstHeaderList = NULL;
  173. }

  174. void CURL网络传输类2::置请求方式(LPCSTR m_Methed) {
  175.     if (lstrcmpA(m_Methed, "GET") == 0)
  176.     {
  177.         curl_easy_setopt(m_curl, CURLOPT_HTTPGET, 1L);
  178.     }
  179.     else if (lstrcmpA(m_Methed, "POST") == 0)
  180.     {
  181.         curl_easy_setopt(m_curl, CURLOPT_POST, 1L);
  182.     }
  183. }

  184. VOID CURL网络传输类2::置重定向次数(INT m_MaxRederects)
  185. {
  186.     if (m_MaxRederects > 0)
  187.     {
  188.         curl_easy_setopt(m_curl, CURLOPT_MAXREDIRS, m_MaxRederects);
  189.         curl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 1);
  190.     }
  191.     else
  192.     {
  193.         curl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 0);
  194.     }
  195. }

  196. void CURL网络传输类2::启用Cookie记录(LPCSTR m_FilePath)
  197. {
  198.     if (m_curl == NULL) {
  199.         return;
  200.     }
  201.     curl_easy_setopt(m_curl, CURLOPT_COOKIEFILE, m_FilePath);
  202.     curl_easy_setopt(m_curl, CURLOPT_COOKIEJAR, m_FilePath);
  203. }

  204. void CURL网络传输类2::置Cookie(LPCSTR m_Cookie)
  205. {
  206.     if (m_curl == NULL) {
  207.         return;
  208.     }
  209.     curl_easy_setopt(m_curl, CURLOPT_COOKIE, m_Cookie);
  210. }

  211. void CURL网络传输类2::置SSLCert(const char* m_CertFile, const char* m_KeyFile, const char* m_KeyPassword)
  212. {
  213.     curl_easy_setopt(m_curl, CURLOPT_SSLCERT, m_CertFile);
  214.     curl_easy_setopt(m_curl, CURLOPT_SSLKEY, m_KeyFile);
  215.     curl_easy_setopt(m_curl, CURLOPT_KEYPASSWD, m_KeyPassword);
  216. }

  217. void CURL网络传输类2::置SSLCertMem(void* lpCerFileData, int CerFileDataLen, const char* lpszCertType,
  218.     void* lpKeyFileData, int nKeyFileDataLen, const char* lpszKeyFileType, const char* lpKeyPassword)
  219. {
  220.     struct curl_blob stblob;
  221.     stblob.data = lpCerFileData;
  222.     stblob.len = CerFileDataLen;
  223.     stblob.flags = CURL_BLOB_COPY;
  224.     curl_easy_setopt(m_curl, CURLOPT_SSLCERT_BLOB, &stblob);
  225.     curl_easy_setopt(m_curl, CURLOPT_SSLCERTTYPE, lpszCertType);

  226.     struct curl_blob blob;
  227.     blob.data = lpKeyFileData;
  228.     blob.len = nKeyFileDataLen;
  229.     blob.flags = CURL_BLOB_COPY;
  230.     curl_easy_setopt(m_curl, CURLOPT_SSLKEY_BLOB, &blob);
  231.     curl_easy_setopt(m_curl, CURLOPT_SSLKEYTYPE, lpszKeyFileType);

  232.     curl_easy_setopt(m_curl, CURLOPT_KEYPASSWD, lpKeyPassword);
  233. }

  234. void CURL网络传输类2::置SSLVerifyPeer(BOOL bVerify)
  235. {
  236.     curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, bVerify);
  237. }

  238. void CURL网络传输类2::置SSLVerifyHost(BOOL bVerify)
  239. {
  240.     curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYHOST, bVerify);
  241. }

  242. const char* CURL网络传输类2::取Url()
  243. {
  244.     char* url = NULL;
  245.     curl_easy_getinfo(m_curl, CURLINFO_EFFECTIVE_URL, &url);
  246.     if (url == NULL) {
  247.         return "";
  248.     }
  249.     return url;
  250. }

  251. const char* CURL网络传输类2::取远端IP()
  252. {
  253.     char* ip;
  254.     curl_easy_getinfo(m_curl, CURLINFO_PRIMARY_IP, &ip);
  255.     if (ip == NULL) {
  256.         return "";
  257.     }
  258.     return ip;
  259. }

  260. INT CURL网络传输类2::取远端端口()
  261. {
  262.     long port;
  263.     curl_easy_getinfo(m_curl, CURLINFO_PRIMARY_PORT, &port);
  264.     return port;
  265. }

  266. INT CURL网络传输类2::取状态码()
  267. {
  268.     long nResponsCode;
  269.     curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &nResponsCode);
  270.     return nResponsCode;
  271. }

  272. const char* CURL网络传输类2::取错误信息()
  273. {
  274.     return m_szErrorBuffer;
  275. }

  276. const char* CURL网络传输类2::取响应头()
  277. {
  278.     return m_ResponsHead.memory;
  279. }

  280. const char* CURL网络传输类2::取响应内容()
  281. {
  282.     return m_ResponsBody.memory;
  283. }

  284. size_t CURL网络传输类2::取响应内容长度()
  285. {
  286.     return m_ResponsBody.size;
  287. }

  288. LPCSTR CURL网络传输类2::取跳转地址()
  289. {
  290.     if (m_curl == NULL) {
  291.         return 0;
  292.     }
  293.     char* url = NULL;
  294.     curl_easy_getinfo(m_curl, CURLINFO_EFFECTIVE_URL, &url);
  295.     return url;
  296. }

  297. LPCSTR CURL网络传输类2::取OriginalCookie()
  298. {
  299.     if (m_curl == NULL) {
  300.         return "";
  301.     }
  302.     ZeroMemory(m_lpszCookies, sizeof(m_lpszCookies));
  303.     struct curl_slist* cookies = NULL;
  304.     CURLcode res = curl_easy_getinfo(m_curl, CURLINFO_COOKIELIST, &cookies);

  305.     if (!res && cookies) {
  306.         struct curl_slist* each = cookies;
  307.         while (each) {
  308.             lstrcatA(m_lpszCookies, each->data);
  309.             each = each->next;
  310.         }
  311.     }
  312.     if (cookies) curl_slist_free_all(cookies);
  313.     return m_lpszCookies;
  314. }

  315. LPCSTR CURL网络传输类2::取Cookies()
  316. {
  317.     if (m_curl == NULL) {
  318.         return "";
  319.     }
  320.     ZeroMemory(m_lpszCookies, sizeof(m_lpszCookies));

  321.     struct curl_slist* cookies, * temp;
  322.     curl_easy_getinfo(m_curl, CURLINFO_COOKIELIST, &cookies);

  323.     temp = cookies;
  324.     while (temp) {
  325.         int nCount = 0;
  326.         char* pOffset = temp->data;
  327.         while (*pOffset != 0)
  328.         {
  329.             if (*pOffset == '\t') {
  330.                 nCount++;
  331.                 if (nCount == 5) break;
  332.             }
  333.             pOffset++;
  334.         }

  335.         pOffset++;
  336.         std::string szKey, szValue;
  337.         while (*pOffset != '\t')
  338.         {
  339.             szKey += *pOffset;
  340.             pOffset++;
  341.         }

  342.         pOffset++;
  343.         szValue = pOffset;

  344.         lstrcatA(m_lpszCookies, szKey.c_str());
  345.         lstrcatA(m_lpszCookies, "=");
  346.         lstrcatA(m_lpszCookies, szValue.c_str());

  347.         temp = temp->next;

  348.         if (temp != NULL)
  349.         {
  350.             lstrcatA(m_lpszCookies, "; ");
  351.         }
  352.     }

  353.     if (cookies)
  354.         curl_slist_free_all(cookies);

  355.     return m_lpszCookies;
  356. }

  357. __int64 CURL网络传输类2::取下载时间()
  358. {
  359.     if (m_curl == NULL) {
  360.         return 0;
  361.     }
  362.     curl_off_t val = 0;
  363.     curl_easy_getinfo(m_curl, CURLINFO_TOTAL_TIME_T, &val);
  364.     return val;
  365. }

  366. __int64 CURL网络传输类2::取下载速率()
  367. {
  368.     if (m_curl == NULL) {
  369.         return 0;
  370.     }
  371.     curl_off_t val = 0;
  372.     curl_easy_getinfo(m_curl, CURLINFO_SPEED_DOWNLOAD_T, &val);
  373.     return val;
  374. }
复制代码

2

主题

4

回帖

38

积分

新手上路

积分
38
 楼主| 发表于 2025-1-3 15:23:22 | 显示全部楼层
20140706 发表于 2025-1-3 15:18
对,测过了,多线程跑不了,多线程下 只有最后一个会正常发送请求,按照网上例子,改了下初始化和清理, ...


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×

66

主题

280

回帖

1277

积分

管理员

积分
1277
发表于 2025-1-3 18:01:00 | 显示全部楼层
反馈给群里管理, 让他们处理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|炫语言 | 炫彩界面库 | 用户所需, 正是我所做! ( 鄂ICP备2023014763号-1 )

GMT+8, 2025-2-5 16:57 , Processed in 0.077105 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表