3. Windows下C++/MFC调用hiredis库操作redis示例

一、头文件目录

    将之前下载和编译好的Redis目录拷贝到新建好的工程目录下面,再点击测试工程的右键/属性,点击C++/常规,附加包含目录添加以下路径,注意如果原先有多个路径,在末尾处添加分号后再粘贴:

3. Windows下C++/MFC调用hiredis库操作redis示例_第1张图片

点击C++/常规,附加包含目录

3. Windows下C++/MFC调用hiredis库操作redis示例_第2张图片

redis-3.0;redis-3.0/src;redis-3.0/deps/hiredis;redis-3.0/deps/linenoise;redis-3.0/deps/lua/src;redis-3.0/src/Win32_Interop;

点击完成即可

二、引入头文件和LIB文件

    参照下面的,在你测试工程中加入以下代码:

#include 
#pragma comment(lib, "ws2_32.lib")

#ifdef _DEBUG
#pragma comment(lib, "redis-3.0/msvs/Win32/Debug/hiredis.lib")
#pragma comment(lib, "redis-3.0/msvs/Win32/Debug/Win32_Interop.lib")
#else
#pragma comment(lib, "redis-3.0/msvs/Win32/Release/hiredis.lib")
#pragma comment(lib, "redis-3.0/msvs/Win32/Release/Win32_Interop.lib")
#endif

三、连接测试

    公共结构体类:

int					m_nId;				// 当前编号
redisContext		*m_pRedis;			// 当前redis服务器指针
ULONGLONG			m_nHeart;			// 最后心跳时间
ULONGLONG			m_nPingSec;			// 检测时间间隔(秒)
char				m_szHost[MAX_PATH];	// redis服务器IP
int					m_nPort;			// redis端口
char				m_szPass[MAX_PATH];	// redis密码
UINT				m_nAuth;			// 网关密码

1、联机、断开

// 释放redis
void redis_disconnect()
{
	if (NULL == m_pRedis)
		return;

	redisFree(m_pRedis);
	m_pRedis = NULL;
	redis_AddLog(/*(%d)已经断开redis数据库.*/XorStr<0x59, 25, 0x1C94563E>("\x71\x7F\x3F\x75\x8F\x8F\xE1\xCD\xD7\xAD\xDC\xCE\x17\x03\x03\x01\x1A\xA0\x96\xD2\xB0\xD1\x8D\x5E" + 0x1C94563E).s, m_nId);
}

// 连接redis
BOOL redis_connect()
{
	redisReply		*reply = NULL;
	struct timeval	timeout = { 3, 500000 };

	redis_disconnect();

	m_pRedis = redisConnectWithTimeout(m_szHost, m_nPort, timeout);
	if (m_pRedis->err)
	{
		redis_AddLog(/*[%s:%d] 连接redis服务器(%d)失败,错误代码: %s*/XorStr<0xC1, 46, 0x955F63A2>("\x9A\xE7\xB0\xFE\xE0\xA2\x9A\xE8\x08\x66\x76\x1F\xBF\xAB\xAB\xB9\xA2\x65\x2D\x1A\x24\x10\x20\xF0\xFC\xBE\xF2\x16\x7A\x6E\x03\x43\x4D\x56\x0E\x2A\x16\x52\x1D\x2A\x02\xD0\xCB\xC9\x9E" + 0x955F63A2).s, m_szHost, m_nPort, m_nId, m_pRedis->errstr);
		redisFree(m_pRedis);
		m_pRedis = NULL;
		return FALSE;
	}
	redis_AddLog(/*[OK] 连接redis服务器(%d)成功 %s:%d*/XorStr<0xAE, 35, 0x232B52CE>("\xF5\xE0\xFB\xEC\x92\x72\x18\x08\x65\xC5\xDD\xDD\xD3\xC8\x0B\x43\x70\x4E\x06\x36\xEA\xE6\xA0\xEC\x75\x0E\x71\x6F\xEA\xEE\xBF\xF7\xEB\xAB" + 0x232B52CE).s, m_nId, m_szHost, m_nPort);

	reply = (redisReply *)redisCommand(m_pRedis, /*AUTH %s*/XorStr<0x72, 8, 0x6E375481>("\x33\x26\x20\x3D\x56\x52\x0B" + 0x6E375481).s, m_szPass);
	if (NULL == reply)
	{
		redis_AddLog(/*[%s] 认证redis服务器(%d)失败,错误代码: %s*/XorStr<0x9E, 43, 0xCE5856B8>("\xC5\xBA\xD3\xFC\x82\x6B\x6B\x73\x02\xD5\xCD\xCD\xC3\xD8\x1B\x53\x60\x5E\x76\x46\x9A\x96\xD0\x9C\x7C\x10\x08\x65\x19\x17\x08\x50\x70\x4C\x74\x3B\x00\x28\xFE\xE5\xE3\xB4" + 0xCE5856B8).s, m_szPass, m_nId, m_pRedis->errstr);
		return FALSE;
	}

	freeReplyObject(reply);
	reply = NULL;

	redis_AddLog(/*[OK] 认证redis服务器成功 (%d)*/XorStr<0xF0, 30, 0xE12E1955>("\xAB\xBE\xB9\xAE\xD4\x3D\x39\x21\x5C\x8B\x9F\x9F\x95\x8E\x49\x01\xCE\xF0\xC4\xF4\xB7\xCC\xBF\xA1\x28\x21\x2F\x6F\x25" + 0xE12E1955).s, m_nId);
	return TRUE;
}

2、选择数据库

// 选择数据库
BOOL redis_selectDB(const UINT uDB)
{
	redisReply	*reply = NULL;
	reply = (redisReply *)redisCommand(m_pRedis, /*SELECT %u*/XorStr<0xF2, 10, 0xC3F71964>("\xA1\xB6\xB8\xB0\xB5\xA3\xD8\xDC\x8F" + 0xC3F71964).s, uDB);
	if (NULL == reply)
	{
		redis_AddLog(/*[%u] 选择redis服务器(%d)失败,错误代码: %s*/XorStr<0x9A, 43, 0x24B46B42>("\xC1\xBE\xE9\xC0\xBE\x4E\x01\x75\x53\xD1\xC1\xC1\xCF\xD4\x1F\x57\x64\x5A\x6A\x5A\x86\x8A\xD4\x98\x78\x14\x04\x69\x15\x1B\x0C\x54\x74\x48\x08\x47\x7C\x54\xFA\xE1\xE7\xB0" + 0x24B46B42).s, uDB, m_nId, m_pRedis->errstr);
		return FALSE;
	}

	if (REDIS_REPLY_ERROR == reply->type)
	{
		redis_AddLog(/*[%u-%d] 选择redis服务器(%d)失败,错误代码: %s*/XorStr<0x3B, 46, 0x88E824CB>("\x60\x19\x48\x13\x1A\x24\x1C\x62\x92\xE5\x91\xB7\x35\x2D\x2D\x23\x38\xFB\xB3\x80\xBE\x96\xA6\x7A\x76\x30\x7C\x9C\xF0\xE8\x85\xF9\xF7\xE8\xB0\x90\xAC\xD4\x9B\xA0\x88\x5E\x45\x43\x14" + 0x88E824CB).s, uDB, reply->type, m_nId, m_pRedis->errstr);
		return FALSE;
	}

	freeReplyObject(reply);
	reply = NULL;
	return TRUE;
}

3、ping

// 根据服务器类型来连接相应的redis服务器
BOOL redis_ping()
{
	redisReply		*reply = NULL;

	if (NULL == m_pRedis)
		return FALSE;

	reply = (redisReply *)redisCommand(m_pRedis, /*PING*/XorStr<0x75, 5, 0x8A439BB6>("\x25\x3F\x39\x3F" + 0x8A439BB6).s);
	if (NULL == reply)
	{
		redis_AddLog(/*[%u] ping redis服务器失败,错误代码: %s*/XorStr<0xF1, 40, 0xD0EF1314>("\xAA\xD7\x86\xA9\xD5\x86\x9E\x96\x9E\xDA\x89\x99\x99\x97\x8C\xB7\xFF\xCC\xF2\xC2\xF2\xCC\xA0\xB8\xD5\xA9\xA7\xB8\xE0\xC0\xFC\xA4\xEB\xD0\xF8\x2E\x35\x33\x64" + 0xD0EF1314).s, m_nId, m_pRedis->errstr);
		return FALSE;
	}

	if (REDIS_REPLY_ERROR == reply->type)
	{
		redis_AddLog(/*[%u-%d] ping redis服务器失败,错误代码: %s*/XorStr<0xF8, 43, 0x0658E001>("\xA3\xDC\x8F\xD6\xD9\x99\xA3\xDF\x70\x68\x6C\x64\x24\x77\x63\x63\x61\x7A\xBD\xF5\xC2\xFC\xC8\xF8\xDA\xB6\xA2\xCF\xB7\xB9\xA2\xFA\xD6\xEA\xAE\xE1\xDE\xF6\x24\x3F\x05\x52" + 0x0658E001).s, m_nId, reply->type, m_pRedis->errstr);
		return FALSE;
	}

	freeReplyObject(reply);
	reply = NULL;
	return TRUE;
}

4、检查心跳保持TCP长链接

// 检查心跳时间
void redis_checkHeart()
{
	if ((MyGetTickCount() - m_nHeart) <= (m_nPingSec * 1000))
		return;

	if (redis_ping())
	{
		redis_update();
	}
	else
	{
		redis_AddLog(/*(%d) redis服务器已连接失败,正在重试...*/XorStr<0xE7, 39, 0x0721955D>("\xCF\xCD\x8D\xC3\xCB\x9E\x88\x8A\x86\x83\x46\x0C\x3D\x05\x33\x01\x25\x29\x38\x56\x46\x2F\x37\x59\x4F\xDC\x2D\xD7\xFE\xD0\xDF\xD0\xDF\xC2\xDD\x24\x25\x22" + 0x0721955D).s, m_nId);
		if (redis_connect())
		{
			redis_AddLog(/*(%d) redis服务器重连接成功...*/XorStr<0x4A, 30, 0xA65E412B>("\x62\x6E\x28\x64\x6E\x3D\x35\x35\x3B\x20\xE3\xAB\x98\xA6\x9E\xAE\x8C\x83\x9D\xF1\xE3\x8C\xD3\xA8\xDB\xC5\x4A\x4B\x48" + 0xA65E412B).s, m_nId);
			redis_update();
		}
	}
}

5、重连机制

// 检查服务器是否连接,否则重连一次
BOOL redis_checkOnlineReconnect()
{
	if (!redis_ping())
	{
		redis_disconnect();
		if (!redis_connect())
		{
			redis_AddLog(/*(%d) redis服务器重连接失败,请检查redis是否在线...*/XorStr<0xA0, 50, 0xD2F7074C>("\x88\x84\xC6\x8A\x84\xD7\xC3\xC3\xC1\xDA\x1D\x55\x62\x5C\x68\x58\x66\x69\x73\x1F\x09\x66\x7C\x10\x08\x65\x96\x7C\x57\x01\x52\x0D\x29\xB3\xA7\xA7\xAD\xB6\x0C\x00\x7F\x38\x1E\x11\x03\x12\xE0\xE1\xFE" + 0xD2F7074C).s, m_nId);
			return FALSE;
		}

		if (!redis_ping())
		{
			redis_AddLog(/*(%d) redis服务器重连接成功,但ping失败,请检查redis是否在线...*/XorStr<0x51, 62, 0x3B40D26D>("\x79\x77\x37\x7D\x75\x24\x32\x3C\x30\x29\xEC\xA2\x93\xAF\x99\x97\xB7\xBA\xA2\xC8\xD8\xB5\xD4\xA1\xD0\xCC\x47\xD9\xC6\x1E\x06\x1E\x16\xB8\xD4\xC4\xA9\xD5\xDB\xBF\x92\xC6\x97\xCE\x94\x0C\x1A\xE4\xE8\xF1\x49\x43\x32\x77\x53\x52\x46\x55\xA5\xA2\xA3" + 0x3B40D26D).s, m_nId);
			return FALSE;
		}
	}

	redis_update();
	return TRUE;
}

6、注意避坑GetTickCount

    这个函数有个致命BUG:已用时间存储为 DWORD 值。 因此,如果系统连续运行 49.7 天,则时间将环绕到零。 若要避免此问题,请使用 GetTickCount64 函数。 否则,在比较时间时,检查溢出条件。

下面是给出的解决办法 :

ULONGLONG MyGetTickCount()
{
	ULONGLONG  ret = 0;

#ifdef _WIN32
	ret = GetTickCount64();
#else
	struct timespec ts;
	clock_gettime(CLOCK_MONOTONIC, &ts);
	ret = (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
#endif
	return ret;
}

你可能感兴趣的:(ASM/WTL/MFC/QT,c++,开发语言,redis,mfc,hiredis)