libcurl长连接高并发高性能

2023-05-16

libcurl长连接高并发高性能

自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取:

https://www.cnblogs.com/bclshuai/p/11380657.html

目录

1 背景介绍

2 长短连接实测分析

2.1 长连接参数设置说明

2.2 长短连接区别

2.2.1 短连接

2.2.2 长连接

2.3 长短连接测试分析

2.3.1 短连接调用url1

2.3.2 长连接调用url1

2.3.3 长连接调用url2

2.3.4 长连接调用两次不同的url

2.3.5 总结分析

3.源码下载地址

1 背景介绍

项目中需要用到Curl频繁调用的情况,发现curl接口调用速度缓慢。为了实现curl高性能,高并发,需要研究如何实现高性能高并发。研究方向有三个。

(1) 长连接。考虑采用长连接的方式去开发。首先研究下长连接和短连接的性能区别。curl内部是通过socket去连接通讯。socket每次连接最为耗时,如果能够复用连接,长时间连接,减少每次socket连接的时间,则可以大大减少时间,提高效率。

(2) 多线程。单个线程下载速度毕竟有限,使用多线程去调用接口。实现高并发高性能,需要考虑资源分配和冲突的问题。

(3) 异步调用。和socket异步调用的原理类似。同步调用会阻塞等待,造成CPU占用率高,电脑卡死等问题。异步调用则是数据接收完成后才会取通知调用成功,处理数据。

2 长短连接实测分析

2.1 长连接参数设置说明

Curl提供了三个参数来设置

/* 设置TCP连接为长连接 */

curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);

/* 设置长连接的休眠时间*/

curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);

/* 设置心跳发送时间,心使得socket长时间保活,小于KEEPIDLE时间 */

curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 20L);

/* 设置连接的超时时间,大于心跳时间*/

curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);

2.2 长短连接区别

2.2.1 短连接

短连接一般分为4步骤:初始化、设置参数、执行请求、清理资源。即使用curl_easy_setopt设置该curl为长连接,因为最后被curl_easy_cleanup(curl),所以这个socket连接会被中断销毁,不会保持长连接。具体步骤如下:

(1)CURL* curl = curl_easy_init();//创建一个curl对象

(2)curl_easy_setopt(curl,……);//可以设置多个参数url,result

(3)res = curl_easy_perform(curl);//执行请求

(4)curl_easy_cleanup(curl);//清除curl

实例代码如下:

int CHttpClient::Get(const std::string & strUrl, std::string & strResponse)

{

int res;

CURL* curl = curl_easy_init();

if (NULL == curl)

{

return CURLE_FAILED_INIT;

}

if (m_bDebug)

{

curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);

curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);

}

curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());

curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);

curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);

/* enable TCP keep-alive for this transfer */

curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);

/* keep-alive idle time to 120 seconds */

curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);

/* interval time between keep-alive probes: 60 seconds */

curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 20L);

curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);

/**

* 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。

* 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。

*/

//curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);

curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 20);

res = curl_easy_perform(curl);

if (res != 0)

{

//FIRE_ERROR(" Get error %d", res);

}

//CurlMutiTreadMutex::GetInstance()->muti_curl_easy_cleanup(curl);

curl_easy_cleanup(curl);

return res;

}

2.2.2 长连接

长连接是我们创建了curl对象之后,不立刻使用curl_easy_cleanup清理掉,而是保存起来,下一个请求,只要重新设置url,执行请求,就可以复用以前的socket连接。

示例代码如下

头文件

CURL* GetCurl();

CURL* CreateCurl();

void PutCurl(CURL* curl);

QVector<CURL*> m_VectCurl;

QMutex m_mutex;

源文件

CURL* RestClientPool::GetCurl()

{

CURL* curl = NULL;

m_mutex.lock();

if (m_VectCurl.size()>0)

{

curl = m_VectCurl.front();

m_VectCurl.pop_front();

}

m_mutex.unlock();

if(curl==NULL)

{

curl = CreateCurl();

}

return curl;

}

CURL* RestClientPool::CreateCurl()

{

CURL* curl = curl_easy_init();

if (NULL == curl)

{

return NULL;

}

if (m_bDebug)

{

curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);

curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);

}

//curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());

curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);

//curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);

/* enable TCP keep-alive for this transfer */

curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);

/* keep-alive idle time to 120 seconds */

curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 300L);

/* interval time between keep-alive probes: 60 seconds */

curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 20L);

curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);

/**

* 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。

* 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。

*/

curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);

curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 20);

return curl;

}

void RestClientPool::PutCurl(CURL* curl)

{

m_mutex.lock();

m_VectCurl.push_back(curl);

m_mutex.unlock();

}

int RestClientPool::Get(const std::string & strUrl, std::string & strResponse)

{

int res;

//CURL* curl = CurlMutiTreadMutex::GetInstance()->muti_curl_easy_init();

CURL* curl = GetCurl();

if (NULL == curl)

{

return CURLE_FAILED_INIT;

}

curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());

curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);

res = curl_easy_perform(curl);

if (res != 0)

{

printf("req error %d",res);

}

PutCurl(curl);

return res;

}

2.3 长短连接测试分析

用上述的长连接和短连接进行测试,分四种情况进行测试分析。

(1) shot连接循环调用1000次url1;

(2) long连接循环调用1000次url1;

(3) long连接循环调用1000次url2;

(4) long连接循环调用1000次,每次循环中各调用一次url1和一次url2;

测试程序代码

#include <QtCore/QCoreApplication>

#include"RestClientPool.h"

#include "RestClient.h"

#include <QDateTime>

#include <string>

using namespace std;

int main(int argc, char *argv[])

{

QCoreApplication a(argc, argv);

CHttpClient m_shotclient;

RestClientPool m_longClient;

QDateTime StartTime = QDateTime::currentDateTime();

string strUrl = "http://qt.gtimg.cn/q=sz002415";

string strUrl2= "http://hq.sinajs.cn/list=sz002415";

string strResponse = "";

for (int i=0;i<1000;i++)

{

m_longClient.Get(strUrl, strResponse);

m_longClient.Get(strUrl, strResponse);

}

QDateTime timeEnd = QDateTime::currentDateTime();

int time = timeEnd.toTime_t()- StartTime.toTime_t();

printf("using time %d", time);

return a.exec();

}

2.3.1 短连接调用url1

如下图所示,短连接每次调用都会创建一个socket连接。

输出

[WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60102[WSPConnect] Socket ip 127.0.0.1:60104线程 0x89b4 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60107[WSPConnect] Socket ip 127.0.0.1:60109线程 0x8de8 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60112[WSPConnect] Socket ip 127.0.0.1:60114线程 0x7d20 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60118[WSPConnect] Socket ip 127.0.0.1:60120线程 0x7e1c 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60124[WSPConnect] Socket ip 127.0.0.1:60126线程 0xa328 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60129[WSPConnect] Socket ip 127.0.0.1:60132线程 0x9a68 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60137[WSPConnect] Socket ip 127.0.0.1:60140线程 0xbd80 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60151[WSPConnect] Socket ip 127.0.0.1:60153线程 0x7360 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60156[WSPConnect] Socket ip 127.0.0.1:60158线程 0xbfac 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60161[WSPConnect] Socket ip 127.0.0.1:60163线程 0xd18 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60166[WSPConnect] Socket ip 127.0.0.1:60168线程 0x8ca8 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60171[WSPConnect] Socket ip 127.0.0.1:60174线程 0xbc88 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60177[WSPConnect] Socket ip 127.0.0.1:60179线程 0x90b0 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60183[WSPConnect] Socket ip 127.0.0.1:60185线程 0x8c38 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60189[WSPConnect] Socket ip 127.0.0.1:60191线程 0xa8d0 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60194[WSPConnect] Socket ip 127.0.0.1:60196线程 0x76a0 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60200[WSPConnect] Socket ip 127.0.0.1:60202线程 0x7c6c 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60205[WSPConnect] Socket ip 127.0.0.1:60208线程 0x8618 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60211[WSPConnect] Socket ip 127.0.0.1:60213线程 0xa300 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60218[WSPConnect] Socket ip 127.0.0.1:60220线程 0xa3f8 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60223[WSPConnect] Socket ip 127.0.0.1:60225线程 0xb81c 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60228[WSPConnect] Socket ip 127.0.0.1:60230线程 0xa554 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 127.0.0.1:60233[WSPConnect] Socket ip 127.0.0.1:60235线程 0xa0f0 已退出,返回值为 0 (0x0)。

2.3.2 长连接调用url1

如下图所示,长连接调用1000次url,只创建了一个socket连接。所用的时间也大幅减少,只有27秒的时间。

输出

WSPStartup ===> D:\Project\CurlHighSpeed\Win32\Release\CurlHighSpeed.exe使用链式SPI[WSPConnect] Socket ip 127.0.0.1:60584[WSPConnect] Socket ip 127.0.0.1:60586WSPStartup ===> D:\Project\CurlHighSpeed\Win32\Release\CurlHighSpeed.exe“CurlHighSpeed.exe”(Win32): 已加载“C:\Program Files (x86)\Sangfor\SSL\ClientComponent\2_SangforNsp.dll”。模块已生成,不包含符号。 “CurlHighSpeed.exe”(Win32): 已卸载“C:\Program Files (x86)\Sangfor\SSL\ClientComponent\2_SangforNsp.dll” “CurlHighSpeed.exe”(Win32): 已加载“C:\Program Files (x86)\Sangfor\SSL\ClientComponent\2_SangforNsp.dll”。模块已生成,不包含符号。 “CurlHighSpeed.exe”(Win32): 已加载“C:\Windows\SysWOW64\dbghelp.dll”。“包括”/“排除”设置禁用了加载功能。 “CurlHighSpeed.exe”(Win32): 已加载“C:\Windows\SysWOW64\rasadhlp.dll”。“包括”/“排除”设置禁用了加载功能。 “CurlHighSpeed.exe”(Win32): 已加载“C:\Windows\SysWOW64\FWPUCLNT.DLL”。“包括”/“排除”设置禁用了加载功能。 “CurlHighSpeed.exe”(Win32): 已加载“C:\Windows\SysWOW64\bcrypt.dll”。“包括”/“排除”设置禁用了加载功能。 线程 0x9adc 已退出,返回值为 0 (0x0)。 [WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 120.204.10.232:80[WSPConnect] Socket ip 120.204.10.232:80“CurlHighSpeed.exe”(Win32): 已加载“C:\Windows\SysWOW64\uxtheme.dll”。“包括”/“排除”设置禁用了加载功能。

2.3.3 长连接调用url2

如下图所示调用不同的url2,调用1000次,用时40秒。所用的时间和url1是不同的,这个和请求的服务器以及请求的数据不一致,所以会有不同的耗时。

WSPStartup ===> D:\Project\CurlHighSpeed\Win32\Release\CurlHighSpeed.exe使用链式SPI[WSPConnect] Socket ip 127.0.0.1:58122[WSPConnect] Socket ip 127.0.0.1:58126

WSPStartup ===> D:\Project\CurlHighSpeed\Win32\Release\CurlHighSpeed.exe“CurlHighSpeed.exe”(Win32): 已加载“C:\Program Files (x86)\Sangfor\SSL\ClientComponent\2_SangforNsp.dll”。模块已生成,不包含符号。

2.3.4 长连接调用两次不同的url

如下图所示,长连接调用两个不同的url。会创建两个socket连接。不会因为切换不同的url,重新创建socket连接。对于每个url会对应一个socket连接。用时82秒,之前分别调用url1和url2所用的时间之和是27+40=67秒,多出来的15秒时间,应该是连接之间的切换时间,所以为了减少时间,可以一种url,用一个curl对象,避免切换。

WSPStartup ===> D:\Project\CurlHighSpeed\Win32\Release\CurlHighSpeed.exe使用链式SPI[WSPConnect] Socket ip 127.0.0.1:58345[WSPConnect] Socket ip 127.0.0.1:58347

2.3.5 总结分析

调用情况用时connect连接次数请求次数单次用时
Shot连接url1147秒1000次10000.147
Long连接url127秒1次10000.027
Long 调用url240秒1次10000.04
Long url1和url282秒2次20000.041

综上所述可以得出结论:

(1) curl初始化,设置参数、调用url、清理cleanup,整个过程会创建一个socket连接。可以先创建,设置为长连接,不清理cleanup,重复使用该curl对象,复用已创建的curl对象和socket连接。可以提高5倍的速度。

(2) 调用不同的url,会因为服务器性能和请求数据量,耗时也会不同。

(3) 一个长连接curl调用两个不同的url(不同的网址),会创建两个socket连接。保持两个socket长连接。不会因为切换不同的url,而重复创建socket连接。切换连接会造成耗时,降低速度20%左右。所以对不同的url,可以用不用的对象和连接,避免切换。提高性能。

3. 源码下载链接

https://download.csdn.net/downl

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

libcurl长连接高并发高性能 的相关文章

  • 在 Mac 上安装 pycurl

    我对 python 非常陌生 需要帮助在我的机器上安装 pycurl 库 我现在正在运行 python 2 7 一个简短的教程将不胜感激 使用两种方法之一 方法一 须藤easy install pycurl 方法二 pip 安装 pycur
  • 如何从 C++ 字符串中删除所有非字母数字字符?

    我正在编写一个软件 它要求我使用 libcurl 处理从网页获取的数据 当我获取数据时 由于某种原因 其中有额外的换行符 我需要找到一种只允许字母 数字和空格的方法 并删除其他所有内容 包括换行符 有什么简单的方法可以做到这一点吗 谢谢 编
  • Curl : * 违反 RFC 2616/10.3.2 并从 POST 切换到 GET

    我正在使用curl 发布到脚本 curl setopt ch CURLOPT POST true curl setopt ch CURLOPT URL url curl setopt ch CURLOPT RETURNTRANSFER 1
  • 通过 PHP Curl 请求 URL 时出现 HTTP 代码 302 错误

    通过 PHP curl exec 请求 url 时收到 302 错误消息 但手动执行时收到代码 200 可能是什么差异导致结果不同 假设我在服务器中有以下代码 url http localhost circle my request sus
  • Android 和 libCurl https

    晚上好 我需要将 libCurl 实现到我们的 Android 项目之一中 我使用 JNI 通过 libCurl 代码调用 C 类 一切都很完美 但看在上帝的份上 我无法使用 https url 让它工作 我总是收到 CURLE UNSUP
  • 从 gchar 缓冲区发送图像到 ftp 服务器 (libcurl)

    我正在开发一个用 C 编程的 Linux 应用程序 它处理 gdk pixbuf 图像 然后通过 ftp libcurl 将它们发送到远程服务器 图像保存到 gchar 缓冲区中gdk pixbuf save to buffer 问题是我不
  • 如何在MacOS10.12下安装libcurl并用于Xcode?

    为 iOS 4 2 构建 libCURL http www creativealgorithms com blog content building libcurl ios 42 大家好 这是我的第一个堆栈溢出问题 我已经阅读了之前发布的博
  • 使用 C++ 的简单 HTTP 请求

    在您将此标记为冗余之前 请注意我已经尝试了网上发布的许多方法 包括堆栈溢出 但它们都无法满足我的需求 另请注意 我对编程世界还很陌生 所以请原谅我滥用技术术语 现在我正在编写一个 C 程序 它计算来自用户计算机的一些数据 例如 IP 地址
  • 取消libcurl轻松处理

    有没有一种简单的方法可以从另一个线程取消curl easy perform 您必须使用回调函数 写入 读取 进度 来执行取消 另一个线程需要设置一个标志 回调函数检查该标志并返回正确的值以取消操作
  • PHP cURL、POST JSON

    我需要发布以下 JSON 代码 但由于某种原因它不起作用 下面是我的代码 fieldString 395609399 the curl request processor function processCurlJsonrequest UR
  • valgrind 在使用 libcurl 时检测内存泄漏(无 ssl)

    在我的 C 程序中 我使用 libcurl 的一些基本函数 今天我运行 valgrind 来检查是否存在内存泄漏 并且 valgrind 疯狂地报告了多个错误 我基本上追踪到 CURL curl CURLcode res curl curl
  • 将 php curl 转换为 GAE urlfetch 以用于 iTunes InApp verifyReceipt

    有人可以帮忙将此 PHP Curl 转换为 UrlFetch 吗 这用于 Apple iTunes verifyReceipt if getiTunesProductionLevel app id sandbox sandbox overr
  • 当我在 PHP 中使用 cURL 发布文件时,是否应该设置 CURLOPT_UPLOAD?

    当我尝试设置它时 它会强制请求方法被 PUT 这是我在 CURLOPT POSTFIELDS 中放入的内容 curl setopt ch CURLOPT POSTFIELDS array fileUpload gt home apache
  • 使用 libcurl 而不使用 dll

    我正在使用 Microsoft Visual C 2010 我需要制作一个不需要 libcurl dll 的应用程序 我在预处理器指令中定义 CURL STATICLIB 并链接到 libcurl lib libcurl static li
  • 使用 PHP 进行 CURL - 非常慢

    All 我必须请求一个返回 JSON 请求的 URL 我正在使用 PHP 和 CURL 来执行此操作 目前 请求和响应大约需要 3 4 秒 以下是curl代码 ch curl init devnull fopen tmp curlcooki
  • 如何将 libcurl 与 dev c++ 静态链接?

    最近我尝试将 libcurl 与 dev c 静态链接 我链接了除来自 libcurl 的 libcurldll a 文件之外的所有 a 文件 并且我定义了 CURL STATICLIB 但我收到了一些链接器错误 然后我在谷歌上搜索了这个链
  • 将变量传递到 CURLOPT_POSTFIELDS C++

    我正在尝试将变量传递到CURLOPT POSTFIELDS 我当前的代码 size t curl write void ptr size t size size t nmemb void stream std string cmd stat
  • 如何正确重复使用卷曲手柄

    我想正确地重用卷曲句柄 这样它就不会给我错误并正常运行 假设我有这段代码 CURL curl curl global init CURL GLOBAL ALL curl curl easy init curl easy setopt cur
  • 如何使用 C++ cURL (libcurl) 管理简单的 PHP 会话

    我正在编写一个 C 客户端 它使用 libcurl 与 PHP 脚本进行通信 通信应该是基于会话的 因此第一个任务是登录并使 PHP 脚本建立会话 我不习惯使用 C 或 PHP 的会话 我基本上知道它与cookies和通信会话id有关 我在
  • curopt_binarytranfer 到底是什么意思?

    我不明白有什么区别 CURLOPT RETURNTRANSFER AND CURLOPT BINARYTRANSFER 我写了一个脚本来检查它

随机推荐