优化域名转IP地址

点击查看源码

getaddrinfo/gethostbyname等方法会到DNS服务器查询域名与IP地址的映射关系,查询过程中需要发送并接收UDP包进行数据交互,这个过程就会产生延时。实际上域名与IP地址的映射关系不会频繁变动,所有没有必要每次都到DNS服务器上查询域名与IP地址的映射关系,我们可以封装一个域名转IP地址的方法,添加一级本地DNS缓存,从而显著提高程序中域名转IP地址的速度。

实现DNS本地缓存前我们需要一把锁用来保存本地缓存,下面我们实现一个自旋锁类(用C++11原子操作实现)

//自旋锁类
class SpinMutex
{
private:
	atomic_flag flag = ATOMIC_FLAG_INIT;

public:
	void lock()
	{
		while (flag.test_and_set(memory_order_acquire));
	}
	void unlock()
	{
		flag.clear(std::memory_order_release);
	}
};

getaddrinfo/gethostbyname等函数的简单包装,提供更简单的接口

//将域名转换成IP地址
const char* GetHostAddress(const char* host, char* ip)
{
#ifndef _MSC_VER    /*LINUX下的实现*/
	struct addrinfo tmp;
	struct addrinfo* res;
	struct sockaddr_in* addr;

	memset(&tmp, 0, sizeof(tmp));

	tmp.ai_family = AF_INET;
	tmp.ai_flags = AI_PASSIVE;
	tmp.ai_socktype = SOCK_STREAM;

	if (getaddrinfo(host, NULL, &tmp, &res) < 0) return NULL;

	addr = (struct sockaddr_in*)(res->ai_addr);
	ip = (char*)(inet_ntop(AF_INET, &addr->sin_addr, ip, 24));

	freeaddrinfo(res);
#else                /*WINDOWS下的实现*/
	struct hostent* entry = gethostbyname(host);

	if (entry == NULL) return NULL;

	sprintf(ip, "%d.%d.%d.%d",
		(entry->h_addr_list[0][0] & 0x00ff),
		(entry->h_addr_list[0][1] & 0x00ff),
		(entry->h_addr_list[0][2] & 0x00ff),
		(entry->h_addr_list[0][3] & 0x00ff));
#endif
	return ip;
}

添加本地DNS缓存,缓存有效时间暂定1分钟

//将域名转换成IP地址
string GetHostAddress(const string& host, bool cache = true)
{
	static SpinMutex mtx;
	static map<string, string> hostmap;

	char buffer[64] = {0};
	time_t now = time(NULL);
	const time_t delay = 60;
	static time_t uptime = 0;

	//检查缓存是否超时
	if (uptime + delay > now)
	{
		std::lock_guard<SpinMutex> lk(mtx);
		hostmap.clear();
		uptime = now;
	}

	//优先从缓存中查询
	while (cache)
	{
		std::lock_guard<SpinMutex> lk(mtx);

		auto it = hostmap.find(host);

		if (it == hostmap.end()) break;

		return it->second;
	}

	GetHostAddress(host.c_str(), buffer);

	//更新缓存
	if (cache)
	{
		std::lock_guard<SpinMutex> lk(mtx);
		hostmap[host] = buffer;
	}

	return buffer;
}

欢迎点击查看完整测试代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值