redis的交叉编译移植以及hiredis的c++封装测试例程

        项目中,有些数据由于环境限制无法实时传输,因此需要将这些数据保存下来,等待条件允许时再传输。redis数据库是一个key-value型的数据库,并且其数据实时保存在内存中,读写速度快,还可以自行配置将内存的数据写入到存储介质的时间间隔,满足实际使用要求。

        由于项目采用的是TI am57xx芯片,因此,需要将redis源码交叉编译移植到板卡上。redis源码交叉编译与其他第三库移植,同样遵循make,make install两个步骤。redis源码采用的是redis-6.2.6.tar.bz2。这个编译redis不需要configure配置。

redis交叉编译移植

        解压,执行下面语句即可。

        make MALLOC=libc CC=arm-linux-gnueabihf-gcc

        编译后如下所示:

        在redis/src路径下,将会生成redis-server, redis-client 等可执行文件

         其中,redis.conf在redis的源码目录下,读者需要将这些文件拷贝到板卡的/bin目录下,将redis.conf拷贝到/etc目录下即可。

        然后在板卡上启动redis服务:

        redis-server /etc/redis.conf &

        启动redis客户端:

        redis-client

        redis的命令可以参考链接http://doc.redisfans.com/

redis的配置文件redis.conf

这里仅介绍常用的一些配置项:

60s至少改动一处即可保存(这里的保存是指真正写入存储介质,而不是停留在内存区)

配置数据库默认名称为dump.rdb

配置默认工作路径:/meida/mmc1p3

配置数据库默认容量:100MB

 配置数据库的保存算法:

以上是此次项目中的常用配置,其他配置项读者可以自行查阅官方文档。

redis.conf更新后,需要将redis.conf重新拷贝到/etc目录下。

redis的c++封装

        这里所说的c++封装,是指作者出于项目的需要,额外重新封装一些接口,内部依旧调用redis的c接口。redis源码自带了redis的c接口,因此,第一需要将这些c接口分离出来。这些c接口函数位于redis/deps/hiredis/目录下:

        先建立一个redis_test目录,在redis_test路径下,再建立include以及src两个子目录;  

      

        将hiredis目录下的头文件拷贝到redis_test/include下:

        将hiredis目录下的源文件拷贝到redis_test/src下:

        注意:example.c、example.cpp以及build_redis_test.sh是自行编写的,后面会提到。拷贝过来的是redis的c接口函数,无需改动。

 编写Redis类,Redis类根际实际使用对外只开放7个接口,分别为判断is_key_exists,设置单个key-valu值set_single_key,获取单个key-value值get_single_key,获取单个key-value并删除getdel_single_key,设置多个key-value值mset_multi_key,获取多个key-value值mget_multi_key,删除多个key值del_list。

每个接口内部,实际调用的依旧是hiredis的c接口,之所以封装,是为了隐去hiredis的实现步骤,读者可专注于使用逻辑。

完整的Redis类实现代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hiredis.h>
#include <win32.h>
#include <unistd.h>

#include <iostream>
#include <string>
#include <list>

using namespace std;

#define VALUE_BUFF_SIZE			(512 * 20)
struct st_key_val
{
	string key;
	uint8_t buff[VALUE_BUFF_SIZE];
	size_t buff_len;
};

typedef list<struct st_key_val> ST_KEY_VAL_LIST;
typedef list<string> ST_KEY_LIST;

class Redis
{
	private:
		string hostname;
		int hostport;
		redisContext *context;
		struct timeval timeout;
		
		int hex2char(uint8_t *buff, int32_t len, string *out_str);
		int char2hex(char *in_str, int32_t in_str_len, uint8_t *out, int32_t out_len);
		
	public:
		long long is_key_exists(const string key);								/* is_key_exists ? */
		int set_single_key(const string key, uint8_t *buff, int32_t len);		/* Set single key--value */
		int get_single_key(const string key, uint8_t *buff, int32_t len);		/* Get single key--value */
		int getdel_single_key(const string key, uint8_t *buff, int32_t len);	/* Get single key--value and delete it */
		
		int mset_multi_key(ST_KEY_VAL_LIST key_val_list);		/* Set multi key--value */
		
		//int mget_multi_key(const string key_list[], int32_t key_num, ST_KEY_VAL_LIST *val_list);		/* Get multi key--value */
		int mget_multi_key(ST_KEY_LIST key_list, ST_KEY_VAL_LIST *val_list);		/* Get multi key--value */
		
		//int del_list(const string key_list[], const int32_t key_num);				 /* Del a list */
		int del_list(ST_KEY_LIST del_key_list);
	public:
		Redis(string name = "127.0.0.1", int port = 6379, int32_t sec = 1, int32_t microsec = 500000)
		{
			redisReply *reply;
			
			hostname = name;
			hostport = port;
			timeout = {sec, microsec};
			
			context = redisConnectWithTimeout(hostname.c_str(), port, timeout);
			if ((context == NULL) || (context->err))
			{
				if (context) 
				{
			        printf("Connection error: %s\n", context->errstr);
			        redisFree(context);
			    } 
				else 
				{
			        printf("Connection error: can't allocate redis context\n");
			    }
			    exit(1);
			}
			
			/* PING server */
			reply = (redisReply *)redisCommand(context,"PING");
			printf("PING: %s\n", reply->str);
			freeReplyObject(reply);
		}
};

long long Redis::is_key_exists(const string key)
{
	redisReply *reply = NULL;
	long long integer = 0;
	const char *c_key = key.c_str();
	
	
	reply = (redisReply *)redisCommand(context,"EXISTS %s", c_key);
	integer = reply->integer;
	freeReplyObject(reply);
	
	return integer;
}

int Redis::set_single_key(const string key, uint8_t *buff, int32_t len)
{
	int32_t i = 0;
	redisReply *reply;
	const char *c_key = key.c_str();
	string s_val;
	char aa[8];
	
	//for (i = 0; i < len; i++)
	//{
	//	sprintf(aa, "%.2x", (uint8_t)buff[i]);
	//	s_val += aa;
	//}
	
	hex2char(buff, len, &s_val);
	
	reply = (redisReply *)redisCommand(context,"SET %s %s", c_key, s_val.c_str());
	printf("SET: %s\n", reply->str);
    freeReplyObject(reply);
	
	return 1;
}

int Redis::get_single_key(const string key, uint8_t *buff, int32_t len)
{
	redisReply *reply = NULL;
	char recv[len] = {'\0'};
	int32_t recv_len = 0;
	
	const char *c_key = key.c_str();
	memset(recv, 0x00, sizeof(recv));
	
	if (is_key_exists(key) == 1)
	{
		reply = (redisReply *)redisCommand(context,"GET %s", c_key);
		if (reply != NULL)
		{
			strcpy(recv, reply->str);
			recv_len = char2hex(recv, reply->len, buff, len);
			freeReplyObject(reply);
		}
	}
	
	return recv_len;
}

int Redis::getdel_single_key(const string key, uint8_t *buff, int32_t len)
{
	redisReply *reply = NULL;
	char recv[len] = {'\0'};
	int32_t recv_len = 0;
	
	const char *c_key = key.c_str();
	memset(recv, 0x00, sizeof(recv));
	
	if (is_key_exists(key) == 1)
	{
		reply = (redisReply *)redisCommand(context,"GETDEL %s", c_key);
		if (reply != NULL)
		{
			strcpy(recv, reply->str);
			recv_len = char2hex(recv, reply->len, buff, len);
			freeReplyObject(reply);
		}
	}
	return recv_len;
}

int Redis::mset_multi_key(ST_KEY_VAL_LIST key_val_list)
{
	redisReply *reply;
	ST_KEY_VAL_LIST::iterator st_key_val;
	string mset_str = "MSET";
	
	for (st_key_val = key_val_list.begin(); st_key_val != key_val_list.end(); st_key_val++)
	{
		mset_str.append(" ");
		mset_str.append(st_key_val->key);
		mset_str.append(" ");
		string s_val;
		hex2char(st_key_val->buff, st_key_val->buff_len, &s_val);
		mset_str.append(s_val);
	}
	
	reply = (redisReply *)redisCommand(context, mset_str.c_str(), NULL);
	//printf("SET: %s\n", reply->str);
    freeReplyObject(reply);
}

#if 0
int Redis::mget_multi_key(const string key_list[], const int32_t key_num, ST_KEY_VAL_LIST *val_list)
{
	redisReply *reply;
	int32_t i = 0;
	struct st_key_val val;
	int32_t val_cn = 0;
	string mget_str = "MGET";
	const char *c_mget_str = NULL;
	
	for (i = 0; i < key_num; i++)
	{
		mget_str.append(" ");
		mget_str.append(key_list[i]);				
	}
	
	c_mget_str = mget_str.c_str();
	reply = (redisReply *)redisCommand(context, c_mget_str, NULL);
	if (reply != NULL)
	{
		if (reply->elements > 0)
		{
			//printf("reply->elements = %d\n", reply->elements);
			for (i = 0; i < reply->elements; i++)
			{
				val.key = key_list[i];
				val.buff_len = char2hex(reply->element[i]->str, reply->element[i]->len, val.buff, VALUE_BUFF_SIZE);
				val_list->push_back(val);
				val_cn++;
			}
		}
		
	}
	freeReplyObject(reply);
	
	return val_cn;
}
#endif

int Redis::mget_multi_key(ST_KEY_LIST key_list, ST_KEY_VAL_LIST *val_list)
{
	redisReply *reply;
	int32_t i = 0;
	struct st_key_val val;
	int32_t val_cn = 0;
	string mget_str = "MGET";
	const char *c_mget_str = NULL;
	
	ST_KEY_LIST::iterator mget_key;
	for (mget_key = key_list.begin(); mget_key != key_list.end(); mget_key++)
	{
		mget_str.append(" ");
		mget_str.append(*mget_key);
	}

	c_mget_str = mget_str.c_str();
	reply = (redisReply *)redisCommand(context, c_mget_str, NULL);
	if (reply != NULL)
	{
		if (reply->elements > 0)
		{
			//printf("reply->elements = %d\n", reply->elements);
			mget_key = key_list.begin();
			for (i = 0; i < reply->elements; i++)
			{
				val.key = *mget_key;
				val.buff_len = char2hex(reply->element[i]->str, reply->element[i]->len, val.buff, VALUE_BUFF_SIZE);
				val_list->push_back(val);
				val_cn++;
				mget_key++;
			}
		}
		
	}
	freeReplyObject(reply);
	
	return val_cn;
}


#if 0
int Redis::del_list(const string key_list[], const int32_t key_num)
{	
	redisReply *reply;
	int32_t i = 0;
	const char *c_list_name;
	string del_str = "DEL";
	
	for (i = 0; i < key_num; i++)
	{
		if (is_key_exists(key_list[i]))
		{
			del_str.append(" ");
			del_str.append(key_list[i]);
		}
	}
	
	c_list_name = del_str.c_str();
	printf("c_list_name = %s\n", c_list_name);
	reply = (redisReply *)redisCommand(context, c_list_name, NULL);
	printf("reply->integer = %lld\n", reply->integer);
	freeReplyObject(reply);
	
	return 0;
}
#endif

int Redis::del_list(ST_KEY_LIST del_key_list)
{
	long long ret = 0;
	redisReply *reply;
	const char *c_list_name;
	string del_str = "DEL";
	
	ST_KEY_LIST::iterator del_key;
	for (del_key = del_key_list.begin(); del_key != del_key_list.end(); del_key++)
	{
		if (is_key_exists(*del_key))
		{
			del_str.append(" ");
			del_str.append(*del_key);
		}
	}
	
	c_list_name = del_str.c_str();
	//printf("c_list_name = %s\n", c_list_name);
	reply = (redisReply *)redisCommand(context, c_list_name, NULL);
	//printf("reply->integer = %lld\n", reply->integer);
	ret = reply->integer;
	freeReplyObject(reply);
	
	return ret;
}

int Redis::hex2char(uint8_t *buff, int32_t len, string *out_str)
{
	//uint8_t tmp = 0x00;
	//int32_t i = 0;
	//int32_t j = 0;
	
	//for (i = 0; i < len; i++)
	//{
	//	for (j = 0; j < 2; j++)
	//	{
	//		tmp = (*(buff + i) >> 4) * (1 - j) + (*(buff + i) & 0x0f) * j;
	//		if ((tmp >= 0) && (tmp <= 9))
	//		{
	//			val[2 * i + j] = tmp + '0';
	//		}
	//		else if ((tmp >= 0x0A) && (tmp <= 0x0F))
	//		{
	//			val[2 * i + j] = tmp - 0x0A + 'A';
	//		}
	//	}
	//}
	
	//string s;
	//char aa[8];
	//for(uint16_t i = 0; i < len; i++)
	//{
	//	sprintf(aa, "%.2x", (uint8_t)buff[i]);
	//	s += aa;
	//}
	
	char aa[8];
	for(uint16_t i = 0; i < len; i++)
	{
		sprintf(aa, "%.2x", (uint8_t)buff[i]);
		out_str->append(aa);
	}
	
	//printf("s = %s\n", s.c_str());
	
	return 0;
}

int Redis::char2hex(char *in_str, int32_t in_str_len, uint8_t *out, int32_t out_len)
{
	char *p = in_str;
	uint8_t high = 0;
	uint8_t low = 0;
	int cnt = 0;
	int32_t ret_len = 0;
	
	while (cnt < in_str_len/2)
	{
		high = ((*p > '9') && ((*p <= 'F') || (*p <= 'f'))) ? *p - 48 - 7 : *p - 48;
		low = (*(++p) > '9' && ((*p <= 'F') || (*p <= 'f'))) ? *p - 48 - 7 : *p - 48;
		
		out[cnt] = (high & 0x0f) << 4 | (low & 0x0f);
		
		p++;
		cnt++;
	}	
	if (in_str_len % 2 != 0)
	{
		out[cnt] = ((*p > '9') && ((*p <= 'F') || (*p <= 'f'))) ? *p - 48 - 7 : *p - 48;
	}
	
	ret_len = in_str_len / 2 + in_str_len % 2;
	
	return ret_len;
}

int main(int argc, char *argv[])
{
	Redis xz_redis;
	
	uint8_t data[] = {0x01, 0x11, 0xa0, 0xff, 0x0f, 0x90};
	uint8_t recv[1024];;
	int32_t recv_len = 0;
	int32_t i = 0;
	
	string del_key[] = {"xu"};
	char val[8];
	
	ST_KEY_VAL_LIST val_list;
	string mget_key[] = {"yc1", "yc2", "yc4", "yc3", "yc7", "yc6", "yc5"};
	ST_KEY_VAL_LIST::iterator st_val;
	int32_t st_val_cn = 0;
	
	ST_KEY_VAL_LIST mset_list;
	struct st_key_val mset_val;
	mset_val.key = "yc5";
	mset_val.buff[0] = 0x58;
	mset_val.buff[1] = 0x58;
	mset_val.buff[2] = 0x58;
	mset_val.buff[3] = 0x58;
	mset_val.buff_len = 4;
	mset_list.push_back(mset_val);
	
	mset_val.key = "yc6";
	mset_val.buff[0] = 0x61;
	mset_val.buff[1] = 0x62;
	mset_val.buff[2] = 0x63;
	mset_val.buff[3] = 0x64;
	mset_val.buff_len = 4;
	mset_list.push_back(mset_val);
	
	mset_val.key = "yc7";
	mset_val.buff[0] = 0x79;
	mset_val.buff[1] = 0x79;
	mset_val.buff[2] = 0x79;
	mset_val.buff[3] = 0x79;
	mset_val.buff_len = 4;
	mset_list.push_back(mset_val);
	
	ST_KEY_LIST del_key_list;
	for (i = 0; i < 7; i++)
	{
		del_key_list.push_back(mget_key[i]);
	}
	
	while(1)
	{
		xz_redis.mset_multi_key(mset_list);
		st_val_cn = xz_redis.mget_multi_key(del_key_list, &val_list);
		printf("st_val_cn = %d\n", st_val_cn);
		for (st_val = val_list.begin(); st_val != val_list.end(); st_val++)
		{
			printf("st_val.key = %s\n", st_val->key.c_str());
			printf("st_val.buff_len = %d\n", st_val->buff_len);
			for (i = 0; i < st_val->buff_len; i++)
				printf("st_val.buff[%d] = %x\n", i, st_val->buff[i]);
		}
		
		xz_redis.del_list(del_key_list);
		
		//xz_redis.del_list(del_key, 1);
		//xz_redis.set_single_key("xu", data, sizeof(data));
		//recv_len = xz_redis.get_single_key("xu", recv, sizeof(recv));
		//if (recv_len > 0)
		//{
		//	printf("recv_len = %d\n", recv_len);
		//	for (i = 0; i < recv_len; i++)
		//		printf("0x%.2x ", recv[i]);
		//	printf("\n");
		//}
		//else
		//{
		//	printf("not exists\n");
		//}
		break;
	}
}

 读者在用上述例子测试时,可以按下面的方法交互测试:

用代码写入key-value,再用redis命令读取,验证是否正确;

用命令写入key-value,再用代码读取,验证是否正确;

注意:上述代码实现的例子,写入的数据均会转成字符串写入到redis中。但因为作者实际使用的数据均为uint8_t数组,因此还做了转换函数,但转换函数不对外开放。

完整的代码实现以及redis的编译资源见链接:​​​​​​https://download.csdn.net/download/qq_36731830/60825216

 

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值