1. Header file directory
Copy the previously downloaded and compiled Redis directory to the newly created project directory, then right-click/properties of the test project, click C++/General, add the following path to the additional include directory. Note that if there are multiple paths originally, add them at the end. Add a semicolon before pasting:
Click C++/General and attach the include directory
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;
Click to finish
2. Introduce header files and LIB files
Refer to the following and add the following code to your test project:
#include <hiredis.h>
#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
3. Connection test
Public structure class:
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. Online, disconnected
// 释放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. Select database
// 选择数据库
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. Check heartbeat and maintain TCP long link
// 检查心跳时间
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. Reconnection mechanism
// 检查服务器是否连接,否则重连一次
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. Pay attention to avoid pitfalls GetTickCount
This function has a fatal bug: the elapsed time is stored as DWORD value. Therefore, if the system runs continuously for 49.7 days, time will wrap around to zero. To avoid this problem, use the GetTickCount64 function. Otherwise, when comparing times, check for an overflow condition.
Here are the solutions given:
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;
}