修改 libcurl 中的 CURLOPT_RESOLVE

modifying CURLOPT_RESOLVE in libcurl

请考虑此代码段,我需要有关在 libcurl

中更改 CURLOPT_RESOLVE 的指导
//snip
#include <curl/curl.h>
#include "myown_dns_client.h"

//just curly things
CURL *hnd;
struct MemoryStruct {
  char *memory;
  size_t size;
};
CURLcode res;
struct curl_slist *slist1 = NULL;
struct MemoryStruct chunk;
//just curly things


int main(){
    //snip//
    return 0;
}

void setup_curl(){
        curl_global_init(CURL_GLOBAL_ALL);
        chunk.memory = NULL;
        chunk.size = 0;

        hnd = curl_easy_init();
        curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
        curl_easy_setopt(hnd, CURLOPT_WRITEDATA, (void *)&chunk);

        if (get_address_from_lookup() ==0){
                // we have updated slist which looks like dns.google.com:443:172.217.14.206
                slist1 = curl_slist_append(NULL, slist);
                curl_easy_setopt(hnd, CURLOPT_RESOLVE,slist1);
                printf(" ** %d Updating slist to %s\n", getpid(), slist);
        }

}

稍后在线程 update_slist 中,如果 dns.google.com 开始解析新地址,例如 216.58.193.78,我想更改 CURLOPT_RESOLVE 选项. (所以我们开始向这个新地址发送请求。)

void *update_slist(void *vargp){
        curl_slist_free_all(slist1);
        struct curl_slist *slist1 = NULL;
        // slist now contains "dns.google.com:443:216.58.193.78"
        slist1 = curl_slist_append(NULL, slist);
       curl_easy_setopt(hnd, CURLOPT_RESOLVE,slist1);
}

不确定这是否是更改 CURLOPT_RESOLVE 的正确方法。尽管有新的 slist1,但我在 netstat -pant 中看到我仍将前往初始地址,而不是新地址。

如有任何建议,将不胜感激,谢谢!

编辑 1

#include <stdio.h>
#include <curl/curl.h>

CURL *curl;
struct curl_slist *host = NULL;
struct curl_slist *temp = NULL;
CURLcode res;
char text[8192];
FILE *popener;

void show_netstat();

int main(){

    char url[] = "https://dns.google.com/resolve?name=www.hulu.com&type=1";

    curl = curl_easy_init();
    host = curl_slist_append(NULL, "dns.google.com:443:172.217.14.206");
    curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
    curl_easy_setopt(curl, CURLOPT_URL, url);

    res = curl_easy_perform(curl);
    show_netstat();
        if(res != CURLE_OK){
        fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
      }


    puts("\nNEXT!");
    temp = curl_slist_append(NULL, "dns.google.com:443:216.58.193.78");
    curl_easy_setopt(curl, CURLOPT_RESOLVE, temp);
    curl_easy_setopt(curl, CURLOPT_URL, url);

    res = curl_easy_perform(curl);
    show_netstat();
        if(res != CURLE_OK){
        fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
      }


    puts("\nDONE!");
    curl_easy_cleanup(curl);
    curl_slist_free_all(host);

    return 0;
}


void show_netstat(){
    popener = popen("netstat -pant 2>/dev/null |grep 443","r");
    fgets(text,8192, popener);
    printf("\n----------------- ------------------- ---------------");
    printf("\n%s", text);
    printf("----------------- ------------------- ---------------\n");
    fclose(popener);
}

ngrep o/p

T 192.168.1.10:53872 -> 172.217.14.206:443 [AP]
T 172.217.14.206:443 -> 192.168.1.10:53872 [A]
T 172.217.14.206:443 -> 192.168.1.10:53872 [A]
T 172.217.14.206:443 -> 192.168.1.10:53872 [AP]
T 192.168.1.10:53872 -> 172.217.14.206:443 [AP]
T 172.217.14.206:443 -> 192.168.1.10:53872 [AP]
T 192.168.1.10:53872 -> 172.217.14.206:443 [AP]
T 172.217.14.206:443 -> 192.168.1.10:53872 [AP]
T 172.217.14.206:443 -> 192.168.1.10:53872 [AP]
T 192.168.1.10:53872 -> 172.217.14.206:443 [AP]
T 172.217.14.206:443 -> 192.168.1.10:53872 [AP] 

编辑 2

Niether 做这个工作:

#include <stdio.h>
#include <curl/curl.h>

CURL *curl;
struct curl_slist *host = NULL;
CURLcode res;


int main(){

    char url[] = "https://dns.google.com/resolve?name=www.hulu.com&type=1";
    curl = curl_easy_init();

    curl_easy_setopt(curl, CURLOPT_URL, url);
    host = curl_slist_append(NULL, "dns.google.com:443:172.217.14.206");
    curl_easy_setopt(curl, CURLOPT_RESOLVE, host);

    res = curl_easy_perform(curl);
        if(res != CURLE_OK){
        fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
      }

    puts("\nNEXT!");
    sleep(3);

        host = curl_slist_append(host, "-dns.google.com:443");
        host = curl_slist_append(host, "dns.google.com:443:216.58.193.78");
        curl_easy_setopt(curl, CURLOPT_RESOLVE, host);

    res = curl_easy_perform(curl);

        if(res != CURLE_OK){
        fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
      }


    puts("\nDONE!");
    curl_easy_cleanup(curl);
    curl_slist_free_all(host);

    return 0;
}

您确实可以通过为完全相同的主机 + 端口设置一个新条目来覆盖之前设置的 CURLOPT_RESOLVE 条目,或者您可以通过传入像 -[host]:[port] 这样的行来清除之前设置的条目(即以破折号开头且没有尾随 :[address])。

只需将该值设置为 NULL 就意味着没有新的条目可以传入,这将使 curl 句柄保持之前已经预填充的数据。

这在 CURLOPT_RESOLVE man page 中有记载。

连接重用注意事项

libcurl 将尝试尽可能重用以前使用的连接,除非您另有说明。如果您向之前使用的同一主机名发出第二次请求,则该连接将被重新使用,并且可能不会使用或检查新的 CURLOPT_RESOLVE 设置。

如果您想真正确保您的第二个请求确实使用了更新后的地址,您必须确保第二次传输不会重用第一次传输时仍然保持活动状态的连接。您可以通过在第一个连接上设置 CURLOPT_FORBID_REUSE 或在第二个连接上设置 CURLOPT_FRESH_CONNECT 来实现此目的。