日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

libcurl 域名解析分析

發布時間:2025/4/5 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 libcurl 域名解析分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景

我們公司的產品使用 libcurl 作為基礎網絡庫,線上環境中經常會有域名解析失敗導致的問題。libcurl 的域名解析默認情況下是調用系統 API 完成的,并且用戶的網絡環境可能比較復雜,比如:是否連接了代理服務器,是否開啟防火墻,域名解析過程是不是被運營商劫持等等。所以對于此類問題,通常是只能在特定的機器和網絡環境下復現,非常難確定具體原因。

排查這類問題中我們也逐步有了一些想法:

  • 網絡診斷工具
  • 域名解析備份機制
  • 域名解析 PK 機制
  • 這篇文章主要記錄一下我是如何實現 libcurl 域名解析 PK 機制的。

    首先需要弄清下面兩個問題:

  • libcurl 的域名解析流程
  • 域名解析 PK 流程
  • libcurl 的域名解析流程

    域名解析是網絡連接的第一步,libcurl 使用了一個狀態機管理網絡連接的每個狀態,代碼在 multi.c 這個文件中:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 static CURLMcode multi_runsingle(struct Curl_multi *multi,struct curltime now,struct Curl_easy *data) {...switch(data->mstate) {case CURLM_STATE_INIT:/* init this transfer. */result=Curl_pretransfer(data);if(!result) {/* after init, go CONNECT */multistate(data, CURLM_STATE_CONNECT);Curl_pgrsTime(data, TIMER_STARTOP);rc = CURLM_CALL_MULTI_PERFORM;}break;case CURLM_STATE_CONNECT_PEND:/* We will stay here until there is a connection available. Thenwe try again in the CURLM_STATE_CONNECT state. */break;case CURLM_STATE_CONNECT:/* Connect. We want to get a connection identifier filled in. */Curl_pgrsTime(data, TIMER_STARTSINGLE);result = Curl_connect(data, &data->easy_conn,&async, &protocol_connect);...case CURLM_STATE_WAITRESOLVE:...result = Curl_resolver_is_resolved(data->easy_conn, &dns);... }

    CURLM_STATE_CONNECT 這個狀態時會發起連接請求 Curl_connect, 解析域名的調用邏輯就封裝在這個方法里面。libcurl 的域名解析有同步和異步兩種方式,默認是異步的方式。異步域名解析的接口定義在 asyn.h 這個頭文件中。

    主要接口如下:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 .../** Curl_resolver_is_resolved()** Called repeatedly to check if a previous name resolve request has* completed. It should also make sure to time-out if the operation seems to* take too long.** Returns normal CURLcode errors.*/ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,struct Curl_dns_entry **dns);/** Curl_resolver_getaddrinfo() - when using this resolver** Returns name information about the given hostname and port number. If* successful, the 'hostent' is returned and the forth argument will point to* memory we need to free after use. That memory *MUST* be freed with* Curl_freeaddrinfo(), nothing else.** Each resolver backend must of course make sure to return data in the* correct format to comply with this.*/ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,const char *hostname,int port,int *waitp); ...

    Curl_resolver_getaddrinfos 是域名解析的接口,具體實現有兩種方式:asyn-thread 和 asyn-ares; 前者是在開啟了一個線程然后調用系統的域名解析API,后者是使用 c-ares 這個庫實現異步域名解析。默認情況下,libcurl 使用的是 asyn-thread, 如果你想使用 asyn-ares, 需要打開 USE_ARES 這個編譯選項。

    Curl_resolver_is_resolved 返回域名解析是否完成,libcurl multi 中有個 hearbeat 就是通過調用這個方法輪詢域名解析是否完成。

    整體流程圖如下:

    ?

    域名解析 PK 流程

    c-ares 是一個跨平臺異步域名解析庫,完整地實現了 DNS 協議標準,沒有使用平臺相關個API;因此,當我們遇到系統域名解析問題時,很自然地想到了是否可以使用 asyn-ares 做 backup 或者同時發起 asyn-thread 和 asyn-ares 兩種解析方式。
    但是 libcurl 中默認只能使用一種域名解析方式,也就時說如果打開了 USE_ARES 編譯選項,就無法使用 aysn-thread 這種方式做域名解析了。所以這里需要重新定義一個編譯選項并實現 asyn 接口。

    如何在 libcurl 中實現域名解析 PK 呢?總結一下有以下需要解決的問題:

  • 并行地發起 asyn-thread 和 asyn-ares 兩種域名解析請求
  • 如果其中一個解析成功
    • 返回解析結果,狀態機更新,繼續處理下一個狀態
    • 取消另一個正在處理的域名解析請求
  • 解析失敗
    • 如果其中一個請求失敗了,忽略失敗處理邏輯,繼續等待另一個域名解析請求返回
    • 如果兩個請求都失敗了,進行失敗處理
  • 取消邏輯
  • 解析狀態檢測
  • 數據結構更新
  • ?

    參考資料

  • 從Chrome源碼看DNS解析過程
  • https://medium.com/tenable-techblog/remotely-exploiting-zoom-meetings-5a811342ba1d
  • 總結

    以上是生活随笔為你收集整理的libcurl 域名解析分析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。