2025年c++ 调用adns库实现DNS解析(全网唯一正确示例)

c++ 调用adns库实现DNS解析(全网唯一正确示例)可以使用一个 adns 的 c 库 版本是 1 6 官方地址 adns advanced alternative asynchronous resolver 下载地址是 http www chiark greenend org uk ian adns ftp adns 1 6 0 tar gz 我实验环境是 ubuntu20

大家好,我是讯享网,很高兴认识大家。

可以使用一个adns的c库,版本是1.6,官方地址:adns - advanced, alternative, asynchronous resolver

下载地址是:http://www.chiark.greenend.org.uk/~ian/adns/ftp/adns-1.6.0.tar.gz

我实验环境是ubuntu20.04

解压,并编译

tar xzvf adns-1.6.0.tar.gz cd adns-1.6.0 ./configure make

讯享网

我没有make install

直接创建了一个测试目录,拷贝静态库

讯享网 mkdir test cp ./src/adns.h ./test cp ./src/libadns.a ./test

建立一个测试文件

test.c

#include "adns.h" #include <arpa/inet.h> #include <netinet/in.h> #include <sys/errno.h> #include <sys/socket.h> int test_dns(char *host) { adns_state ads; adns_initflags flags; flags = (adns_initflags)(adns_if_nosigpipe | adns_if_noerrprint); adns_init(&ads, flags, NULL); adns_query quer = NULL; adns_submit(ads, host, (adns_rrtype)adns_r_a, (adns_queryflags)0, NULL, &quer); int tryCount = -1; int adns_cname = 0; adns_answer *ans = NULL; while (tryCount < 32) { tryCount += 1; int res = adns_check(ads, &quer, &ans, NULL); if (res == 0) { if (ans->status == adns_s_prohibitedcname) { char cname[128]; strncpy(cname, ans->cname, 127); printf("cname = %s \n", ans->cname ); cname[strlen(ans->cname)] = '\0'; //if (quer) // free(quer); if (ans) free(ans); ans = NULL; quer = NULL; adns_submit(ads, cname, (adns_rrtype)adns_r_addr, (adns_queryflags)0, NULL, &quer); adns_cname = 1; } else { // resolve IPv4 address if (adns_cname) { printf("ip: %s\n", ans->status == adns_s_ok ? inet_ntoa(ans->rrs.addr->addr.inet.sin_addr) : "no"); } else { printf("ip: %s\n", ans->status == adns_s_ok ? inet_ntoa(*(ans->rrs.inaddr)) : "no"); } adns_finish(ads); ads = NULL; break; } } else if (res == ESRCH || res == EAGAIN) { usleep(1000); } else { printf("host(%s) is err!\n", host); } } //if (quer) // free(quer); if (ans) free(ans); if (ads) { printf("time out to find\n"); adns_finish(ads); } return 0; } int main(int argc, char *argv[]) { char host[128]; while (1) { scanf("%s", host); if (strlen(host) == 4 && 0 == strcmp(host, "exit")) break; test_dns(host); } return 0; } 

这里解释一下,为什么不直接用wait,而非要做一个循环检测,主要是因为首次返回的可能是别名,而不是地址,必须要递归检测一下才能获取真实地址;


讯享网

另外注意内存释放!!!

手动编译

讯享网gcc -o test ./test.c -L./ -ladns

生成test文件,

执行一下内存测试:

valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --undef-value-errors=no --log-file=log.txt ./test www.sohu.com cname = gs.a.sohu.com ip: 123.125.116.12 www.baidu.com ip: 182.61.200.7 www.github.com ip: 20.205.243.166 exit 

==============华丽的分割线======================================

这里再附赠一个真正可以用的c++版本:

讯享网/ * @file dns_test.cpp * @author robin (@.com) * @brief example to show how to use libadns to parse domain name, and use it in a worker thread * @version 0.1 * @date 2022-05-12 * * @copyright Copyright (c) 2022 * * build: gcc ./test.cpp -std=c++11 -L./ -ladns -lpthread -lstdc++ -w -g -o test * valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --undef-value-errors=no --log-file=log.txt ./test */ #include <arpa/inet.h> #include <netinet/in.h> #include <sys/errno.h> #include <sys/socket.h> // just for cpp, #include <stdlib.h> #include <string.h> #include <string> #include <map> #include <thread> #include <memory> #include <functional> #include <deque> #include <mutex> #include <iostream> using namespace std; #ifdef __cplusplus extern "C" { #include "adns.h" } #endif class Info { public: Info(const string & s, const adns_query& q) : url(s), quer(q), state(0), ipv4(""), isCName(false) { } string url; adns_query quer; int state; string ipv4; bool isCName; Info() = delete; //Info(const Info &) = delete; // time; }; using InfoPtr = std::shared_ptr<Info>; using dnsCallback = std::function<void (const InfoPtr & info)>; class Dns { public: Dns(); virtual ~Dns(); void init(dnsCallback & fn); void query(const std::string & url); void pollStat(); size_t getQueSize() { return infoQue.size(); } private: adns_state ads; adns_initflags flags; std::deque<string> urlQue; // client push url into it std::mutex mutexQue; std::deque<InfoPtr> infoQue; // work use this que without lock dnsCallback cb; private: bool checkState(InfoPtr & info); }; Dns::Dns() { cb = nullptr; flags = (adns_initflags)(adns_if_nosigpipe | adns_if_noerrprint); ads = NULL; } Dns::~Dns() { if (ads) { adns_finish(ads); } cb = nullptr; } void Dns::init(dnsCallback & fn) { cb = fn; adns_init(&ads, flags, NULL); } void Dns::query(const std::string & url) { std::lock_guard<std::mutex> guard(mutexQue); urlQue.emplace_back(url); } void Dns::pollStat() { // auto lock { std::lock_guard<std::mutex> guard(mutexQue); for (string & url : urlQue) { adns_query quer; int ret = adns_submit(ads, url.c_str(), (adns_rrtype)adns_r_a, (adns_queryflags)0, NULL, &quer); InfoPtr info = std::make_shared<Info>(url, quer); infoQue.emplace_back(info); } urlQue.clear(); } std::deque<InfoPtr> temp; while (infoQue.size() > 0) { // get one and test it InfoPtr info = infoQue[0]; infoQue.pop_front(); bool bFinish = checkState(info); if (bFinish) { // notify user that, we finished one if (cb != nullptr) { cb(info); } } else { temp.emplace_back(info); } } infoQue.swap(temp); } bool Dns::checkState(InfoPtr & info) { adns_answer *ans = nullptr; int res = adns_check(ads, &(info->quer), &ans, NULL); if (res == 0) { if (ans->status == adns_s_prohibitedcname) { info->isCName = true; string cname(ans->cname, 0, 127); if (ans != nullptr) free(ans); ans = NULL; info->quer = nullptr; adns_submit(ads, cname.c_str(), (adns_rrtype)adns_r_addr, (adns_queryflags)0, NULL, &(info->quer)); return false; } else { // resolve IPv4 address //printf("status = %d\n", ans->status); if (info->isCName) { if (ans->status == adns_s_ok) { info->ipv4 = inet_ntoa(ans->rrs.addr->addr.inet.sin_addr); } } else { if (ans->status == adns_s_ok) { info->ipv4 = inet_ntoa(*(ans->rrs.inaddr)); } } info->state = ans->status; if (ans != nullptr) free(ans); ans = NULL; return true; } } else if (res == ESRCH || res == EAGAIN) { info->state = -1; //usleep(); return false; } else { info->state = -2; return true; } } // test the callback function void onFinishDns(const InfoPtr & info) { cout << info->state << ", "; cout << info->url << " : "; cout << info->ipv4 << endl; } bool bStop = false; void workerFun(Dns * dns) { while (bStop == false) { dns->pollStat(); usleep(1000); } } int main(int argc, char *argv[]) { Dns dns; dnsCallback cb = onFinishDns; dns.init(cb); char host[128]; std::thread workerThread = std::thread(workerFun, &dns); while (1) { scanf("%s", host); if (strlen(host) == 4 && 0 == strcmp(host, "exit")) break; dns.query(host); } bStop = true; if (workerThread.joinable()) { workerThread.join(); } cout << "process exit!" << endl; return 0; } 

小讯
上一篇 2025-02-14 22:27
下一篇 2025-03-30 16:23

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/41525.html