【背景】
项目中用到c-ares 64位,是Windows + 2010组合,编译比较简单,直接有工程,简单修改相关配置,就编译成功了。但是写demo测试时,碰到"Misformatted domain name"错误。于是简单排查了一下,过程记录一下,以备不时查询。
【过程】
来自网上的代码片:
#include "test_cares.h"
#include "ares.h"
#include <time.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#if defined (WIN32) || defined (WIN64)
# pragma comment(lib, "ws2_32.lib")
#else
# include <netdb.h>
# include <arpa/inet.h>
#endif
void dns_callback (void* arg, int status, int timeouts, struct hostent* host)
{
if(status == ARES_SUCCESS)
{
std::cout <<"ip : "<<"8.8.8.8"<<std::endl<<"host name : "<< host->h_name << "\n";
}
else
{
std::cout << "lookup failed: " << status << '\n';
}
}
void main_loop(ares_channel &channel)
{
int nfds, count;
fd_set readers, writers;
timeval tv, *tvp;
while (1)
{
FD_ZERO(&readers);
FD_ZERO(&writers);
nfds = ares_fds(channel, &readers, &writers);
if (nfds == 0)
break;
tvp = ares_timeout(channel, NULL, &tv);
count = select(nfds, &readers, &writers, NULL, tvp);
ares_process(channel, &readers, &writers);
}
}
int DEMO::get_url_by_ip(char* in_ip/* = "8.8.8.8"*/)
{
// 注释0
#if 0
int version;
const char* pversion = ares_version(&version);
std::cout<<"version : "<<pversion<<std::endl;
struct in_addr ip_test;
ares_inet_pton(AF_INET, in_ip, &ip_test);
char szIP[1024];
ares_inet_ntop(AF_INET, &ip_test, szIP, 1024);
#endif
// 注释1
WSADATA wsData;
::WSAStartup(MAKEWORD(2,2), &wsData);
// 注释2
int rc1 = ares_library_init(ARES_LIB_INIT_ALL);
ares_channel channel;
int rc2 = ares_init(&channel);
if(rc2 != ARES_SUCCESS)
{
const char* err = ares_strerror(rc2);
std::cout << "ares_init fail : code=" << rc2 <<", err="<<err<< std::endl;
return -1;
}
struct in_addr ip;
ares_inet_pton(AF_INET, in_ip, &ip);
ares_gethostbyaddr(channel, &ip, sizeof ip, AF_INET, dns_callback, NULL);
main_loop(channel);
std::cout<<"ares test finish"<<std::endl;
return 0;
}
google来的代码片没有【注释0】,【注释1】,【注释2】 三个部分。
调试,第一次报错信息为:"c-ares library initialization not yet performed"
这个简单,一看文档就发现【注释2】部分,加个初始化函数就行,当然实际使用要注意调用相应的清理函数。
继续调试,第二次报错信息为:"Misformatted domain name"
这个错误查不到什么有用的资料,那就做个简单测试。
先来看看c-ares的基本函数能不能用。于是加入【注释0】部分代码,发现工作全部正常。
ok,那么库应该没问题了,可以从使用的角度切入。
那就调试进源码看看,发现报错位置在init_by_defaults里调用gethostname时返回失败。
顺手查一下gethostname的失败原因,baidu到的简单粗暴:
调用gethostname之前, 要先调用WSAStartup才可以, 否则gethostname会失败!
于是加上【注释1】的代码进行初始化,继续调试,成功。