我正在使用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永远不会回来.

但是,我需要在同一连接上将数据传输到服务器,例如订阅数据项.但是根据我对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;
}

C++相关问答推荐

rSP堆栈指针在返回函数调用的值时有任何用途吗?

我可以动态分配具有空类型函数的矩阵吗?

错误:在.h程序中重新定义 struct

与unions 的未定义行为

特定闪存扇区的内存别名

错误:包含文件时类型名称未知

Kdb:仅升级指定的列

是否需要包括<;errno.h>;才能使用perror?

等同于铁 rust 的纯C语言S未实现!()宏

C I/O:在Windows控制台上处理键盘输入

如何用C语言为CLI应用程序编写按键检测系统?

使用nmake for程序比Hello World稍微复杂一些

试图创建一个基本的Word克隆,但遇到了障碍

使用正则表达式获取字符串中标记的开始和结束

如何使用空元素块声明指针数组

CS50 pset 5的皱眉脸正确地处理了大多数基本单词,并且拼写判断不区分大小写.

如何使用calloc和snprintf

无算术运算符和循环的二进制乘法

C语言中的指针和多维数组

execve 不给出which命令的输出