如何在持久连接中使用 libcurl 发送数据?
How to send data with libcurl in persistent connections?
我正在使用 libcurl 连接到 LightStreamer 服务器。考虑以下最小示例:
#include <curl/curl.h>
static size_t writeCallback(char *ptr, size_t size, size_t nmemb, void* userdata)
{
printf("%.*s\n", size * nmemb, ptr);
return size * nmemb;
}
int main() {
const char url[] =
"http://push.lightstreamer.com/lightstreamer/create_session.txt?LS_protocol=TLCP-2.0.0";
const char data[] =
"LS_adapter_set=DEMO&LS_cid=mgQkwtwdysogQz2BJ4Ji%20kOj2Bg";
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, sizeof(data));
curl_easy_perform(curl);
return 0;
}
当运行这个时候,服务器永远不会关闭连接;这意味着 curl_easy_perform
永远不会 returns.
但是,我需要在同一个连接上向服务器传输数据,例如订阅数据项。但是根据我对 curl 文档的理解,我不应该在第一个 perform
仍然是 运行.
时第二次调用 curl_easy_perform
这是如何实现的?我查看了 multi
接口的文档,但我不确定这是否是我需要的。
#include <curl/curl.h>
static size_t writeCallback(char *ptr, size_t size, size_t nmemb, void* userdata) {
printf("%.*s\n", size * nmemb, ptr);
return size * nmemb;
}
static size_t headerCallback(char *buffer, size_t size, size_t nitems, void *userdata) {
int *keep_running = (int *)userdata;
if (nitems * size == 2 && !strncmp(buffer, "\r\n", 2))
*keep_running = 0;
return nitems * size;
}
int main() {
const char url[] =
"http://push.lightstreamer.com/lightstreamer/create_session.txt?LS_protocol=TLCP-2.0.0";
const char data[] =
"LS_adapter_set=DEMO&LS_cid=mgQkwtwdysogQz2BJ4Ji%20kOj2Bg";
CURL *curl = curl_easy_init();
int keep_running = 1; // keep running until response headers received
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, headerCallback);
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &keep_running);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, sizeof(data));
CURLM *multi_handle = curl_multi_init();
curl_multi_add_handle(multi_handle, curl);
CURLMcode mc;
int still_running = 1; // keep number of running handles
do {
mc = curl_multi_perform(multi_handle, &still_running);
if (!mc) {
// wait for activity, timeout or "nothing"
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
}
if(mc) {
fprintf(stderr, "curl_multi_poll() failed, code %d.\n", (int)mc);
break;
}
} while(keep_running && still_running);
int queed = 0;
CURLMsg *msg = curl_multi_info_read(multi_handle, &queed);
if (msg && (msg->msg == CURLMSG_DONE)) {
// request finished
CURLcode rc = msg->data.result;
} else if (!mc) {
// request is alive
curl_socket_t sockfd;
if (!curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd)) {
do {
if (write(sockfd, "OK\r\n", 4) < 0)
break;
// keep alive
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
if(mc)
break;
} while (still_running);
}
}
curl_multi_remove_handle(multi_handle, curl);
curl_easy_cleanup(curl);
curl_multi_cleanup(multi_handle);
curl_global_cleanup();
return 0;
}
我正在使用 libcurl 连接到 LightStreamer 服务器。考虑以下最小示例:
#include <curl/curl.h>
static size_t writeCallback(char *ptr, size_t size, size_t nmemb, void* userdata)
{
printf("%.*s\n", size * nmemb, ptr);
return size * nmemb;
}
int main() {
const char url[] =
"http://push.lightstreamer.com/lightstreamer/create_session.txt?LS_protocol=TLCP-2.0.0";
const char data[] =
"LS_adapter_set=DEMO&LS_cid=mgQkwtwdysogQz2BJ4Ji%20kOj2Bg";
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, sizeof(data));
curl_easy_perform(curl);
return 0;
}
当运行这个时候,服务器永远不会关闭连接;这意味着 curl_easy_perform
永远不会 returns.
但是,我需要在同一个连接上向服务器传输数据,例如订阅数据项。但是根据我对 curl 文档的理解,我不应该在第一个 perform
仍然是 运行.
curl_easy_perform
这是如何实现的?我查看了 multi
接口的文档,但我不确定这是否是我需要的。
#include <curl/curl.h>
static size_t writeCallback(char *ptr, size_t size, size_t nmemb, void* userdata) {
printf("%.*s\n", size * nmemb, ptr);
return size * nmemb;
}
static size_t headerCallback(char *buffer, size_t size, size_t nitems, void *userdata) {
int *keep_running = (int *)userdata;
if (nitems * size == 2 && !strncmp(buffer, "\r\n", 2))
*keep_running = 0;
return nitems * size;
}
int main() {
const char url[] =
"http://push.lightstreamer.com/lightstreamer/create_session.txt?LS_protocol=TLCP-2.0.0";
const char data[] =
"LS_adapter_set=DEMO&LS_cid=mgQkwtwdysogQz2BJ4Ji%20kOj2Bg";
CURL *curl = curl_easy_init();
int keep_running = 1; // keep running until response headers received
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, headerCallback);
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &keep_running);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, sizeof(data));
CURLM *multi_handle = curl_multi_init();
curl_multi_add_handle(multi_handle, curl);
CURLMcode mc;
int still_running = 1; // keep number of running handles
do {
mc = curl_multi_perform(multi_handle, &still_running);
if (!mc) {
// wait for activity, timeout or "nothing"
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
}
if(mc) {
fprintf(stderr, "curl_multi_poll() failed, code %d.\n", (int)mc);
break;
}
} while(keep_running && still_running);
int queed = 0;
CURLMsg *msg = curl_multi_info_read(multi_handle, &queed);
if (msg && (msg->msg == CURLMSG_DONE)) {
// request finished
CURLcode rc = msg->data.result;
} else if (!mc) {
// request is alive
curl_socket_t sockfd;
if (!curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd)) {
do {
if (write(sockfd, "OK\r\n", 4) < 0)
break;
// keep alive
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
if(mc)
break;
} while (still_running);
}
}
curl_multi_remove_handle(multi_handle, curl);
curl_easy_cleanup(curl);
curl_multi_cleanup(multi_handle);
curl_global_cleanup();
return 0;
}