网站改了关键词如何删除网站黑链
网站改了关键词,如何删除网站黑链,dj那个网站做的好,云南旅游网站一、hiredis源码安装说明 本文创作基于 hiredisv1.2.0版本 1.简介
hiredis是一个用于与Redis交互的C语言客户端库。它提供了一组简单易用的API#xff0c;使开发人员可以轻松地连接到Redis服务器#xff0c;并执行各种操作#xff0c;如设置和获取键值对、执行命令、订阅和…一、hiredis源码安装说明 本文创作基于 hiredisv1.2.0版本 1.简介
hiredis是一个用于与Redis交互的C语言客户端库。它提供了一组简单易用的API使开发人员可以轻松地连接到Redis服务器并执行各种操作如设置和获取键值对、执行命令、订阅和发布消息等。hiredis的设计目标是高效性和简单性。它使用纯C语言编写没有外部依赖可以轻松地与任何C/C项目集成。它具有轻量级的实现和低延迟的性能适用于高并发的应用场景。hiredis支持同步和异步的方式与Redis进行通信。同步方式是指客户端发送一个命令后会一直等待Redis的响应直到响应返回后才继续执行下一个命令。异步方式是指客户端发送命令后可以继续执行其他任务通过回调函数来处理Redis的响应。除了基本的Redis操作hiredis还提供了一些高级功能如管道操作和事务。管道操作允许一次性发送多个命令到Redis以减少网络开销。事务可以将一系列命令打包成一个原子操作保证它们的执行是连续的。
总之hiredis是一个简单、高效的C语言客户端库使开发人员可以轻松地与Redis进行交互。它适用于任何需要与Redis集成的C/C项目并且具有良好的性能和灵活性。
2.下载源码
hiredis官网https://redis.io/lp/hiredis/ hiredis githubhttps://github.com/redis/hiredis/releases
3.安装说明
# 下载软件包解压并移动目标位置
[rootAli ~]# wget https://github.com/redis/hiredis/archive/refs/tags/v1.2.0.tar.gz
[rootAli ~]# tar xzvf v1.2.0.tar.gz
[rootAli ~]# mv hiredis-1.2.0 /usr/local/redis/hiredis# 安装依赖
[rootAli hiredis]# yum install openssl-devel -y# 编译安装 hiredis
[rootAli hiredis]# make
[rootAli hiredis]# make install
mkdir -p /usr/local/include/hiredis /usr/local/include/hiredis/adapters /usr/local/lib
cp -pPR hiredis.h async.h read.h sds.h alloc.h sockcompat.h /usr/local/include/hiredis
cp -pPR adapters/*.h /usr/local/include/hiredis/adapters
cp -pPR libhiredis.so /usr/local/lib/libhiredis.so.1.1.0
cd /usr/local/lib ln -sf libhiredis.so.1.1.0 libhiredis.so ln -sf libhiredis.so.1.1.0 libhiredis.so.1
cp -pPR libhiredis.a /usr/local/lib
mkdir -p /usr/local/lib/pkgconfig
cp -pPR hiredis.pc /usr/local/lib/pkgconfig 可以看到make install成功后 hiredis头文件 安装放在/usr/local/include/hiredis库文件放在 /usr/local/lib/ 目录下 adapters 注意 使用上述编译生成的so不支持SSL若想支持SSL需要再编译增加USE_SSL1参数如make USE_SSL1 make install USE_SSL1 【参考 hiredis-README】 二、hiredis 使用说明
值得说明的是hiredis支持 同步 和 异步 两种调用方式。无论同步还是异步使用hiredis 基本流程都是以下三个步骤
使用 redisConnect 连接数据库使用 redisCommand 执行命令释放对象 使用 freeReplyObject 释放 redisReply 对象使用 redisFree 来释放redisContext。
1. 简单示例
本小节以一个最简单的 同步API调用 示例帮助读者建立API使用的整体过程。
一个最简单的API调用为例至少需要引入以下几个函数
/* 创建一个redis链接并返回一个redis上下文 */
redisContext *redisConnect(const char *ip, int port);/* 执行redis操作命令 */
void *redisCommand(redisContext *c, const char *format, ...);
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
void redisAppendCommand(redisContext *c, const char *format, ...);
void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);/*释放资源*/
void freeReplyObject(void *reply);
void redisFree(redisContext *c);示例代码
#include stdio.h
#include string.h
#include hiredis/hiredis.hint main(){redisReply *lpReply nullptr;redisContext *lpContext nullptr;/* 创建一个redis链接 */lpContext redisConnect(127.0.0.1, 6379);if (lpContext NULL || lpContext-err) {if (lpContext) {printf(Error: %s\n, lpContext-errstr);// handle error} else {printf(Cant allocate redis context\n);}}/* 执行redis操作命令 */// void *redisCommand(redisContext *c, const char *format, ...);lpReply (redisReply*)redisCommand(lpContext, SET foo %s, 12345);printf(type%d, value%d\n, lpReply-type, lpReply-integer);/* 释放一个响应对象 */freeReplyObject(lpReply);lpReply (redisReply*)redisCommand(lpContext, GET foo);printf(type%d, value%s\n, lpReply-type, lpReply-str);/* 释放一个响应对象 */freeReplyObject(lpReply);/* 是否上下文 */redisFree(lpContext);
}
运行结果
# 执行前redis中不存在foo的key
[wengjianhongAli testzone]$ redis-cli
127.0.0.1:6379 get foo
(nil)
127.0.0.1:6379# 编译运行
[wengjianhongAli testzone]$ g test_hiredis.cpp --stdc11 -lhiredis -o test_hiredis
[wengjianhongAli testzone]$ ./test_hiredis
type5, value0
type1, value12345# 执行后获取 redis中foo的值
[wengjianhongAli testzone]$ redis-cli
127.0.0.1:6379 get foo
12345
127.0.0.1:6379
2.同步API说明
建立链接
/* 建立连接 */
redisContext *redisConnect(const char *ip, int port);/* 带参数的建立连接 */
redisContext *redisConnectWithOptions(const redisOptions *options);/* 重连重连时自动使用保存在上下文的参数 */
int redisReconnect(redisContext *c);/* 此外redis还有如下的建立连接的接口底层上也是调用 redisConnectWithOptions */
redisContext *redisConnectNonBlock(const char *ip, int port);
redisContext *redisConnectBindNonBlock(const char *ip, int port, const char *source_addr);
redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, const char *source_addr);
redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);
redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);
redisContext *redisConnectUnixNonBlock(const char *path);
redisContext *redisConnectUnix(const char *path);
redisContext *redisConnectFd(redisFD fd);
其中调用建连接口返回redis上下文 redisContext 注意: redisContext不是线程安全的其中保存hiredis的连接状态。 redisContext 中包含一个非零的整数err字段和一个带有错误描述的字符串字段。
/* Context for a connection to Redis */
typedef struct redisContext {const redisContextFuncs *funcs; /* Function table */int err; /* Error flags, 0 when there is no error */char errstr[128]; /* String representation of error when applicable */// ... ...
} redisContext;在使用redisConnect连接到Redis后应该检查err字段看看建立连接是否成功如
redisContext *c redisConnect(127.0.0.1, 6379);
if (c NULL || c-err) {if (c) {printf(Error: %s\n, c-errstr);// handle error} else {printf(Cant allocate redis context\n);}
}注意套接字选项直接应用于底层套接字不会存储在 redisConnext 中因此调用 redisReconnect 重连的时候必须重新设置。如
int redisEnableKeepAlive(redisContext *c);
int redisEnableKeepAliveWithInterval(redisContext *c, int interval);
int redisSetTcpUserTimeout(redisContext *c, unsigned int timeout);发送命令
hiredis支持多种向Redis发出操作指令的接口函数原型如下
/*** brief 使用格式化字符串* param c redis上下文指针* param format 参数格式化字符串* param 参数* return redisReply 结构体指针
*/
void* redisCommand(redisContext* c, const char* format, ...);/* 使用 argc、argv 参数列表 */
/*** brief 使用 argc、argv 参数列表* param c redis上下文指针* param argc 参数个数* param argv 参数指针数组* param argvlen 参数长度数组* return redisReply 结构体指针
*/
void* redisCommandArgv(redisContext* c, int argc, const char** argv, const size_t* argvlen);上述的三个接口
执行成功时返回值 void* 实际上是 redisReply* 结构体如下。执行失败时返回值为NULL并且将设置上下文中的err字段(请参阅错误部分)。
注意一旦返回错误上下文就不能被重用您应该建立一个新的连接。
/* This is the reply object returned by redisCommand() */
typedef struct redisReply {int type; /* REDIS_REPLY_* */long long integer; /* The integer when type is REDIS_REPLY_INTEGER */size_t len; /* Length of string */char* str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */
} redisReply;示例 示例1
void* lpRelay redisCommand(context, SET foo bar);
void* lpRelay redisCommand(context, SET foo %s, value);
void* lpRelay redisCommand(context, SET %s %s, key, value);
void* lpRelay redisCommand(context, SET foo %b, value, (size_t) valuelen); /* 二进制参数 需要指定长度 *//// 示例2
int argc 3;
const char *argv[] {SET, foo3, bar3};
size_t argvlen[] {strlen(argv[0]), strlen(argv[1]), strlen(argv[2])};
void* lpReply (redisReply*)redisCommandArgv(lpContext, argc, argv, argvlen);hiredis 还支持管道的命令方式 和 显示的获取回复
/* Write a command to the output buffer. Use these functions in blocking mode* to get a pipeline of commands. */
void redisAppendCommand(redisContext *c, const char *format, ...);
void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);/* 获取返回结果 */
int redisGetReply(redisContext *c, void **reply);
int redisGetReplyFromReader(redisContext *c, void **reply);示例
// 示例1
redisReply *reply;
redisAppendCommand(context,SET foo bar);
redisAppendCommand(context,GET foo);
redisGetReply(context,(void**)reply); // reply for SET
freeReplyObject(reply);
redisGetReply(context,(void**)reply); // reply for GET
freeReplyObject(reply);// 示例2
reply redisCommand(context,SUBSCRIBE foo);
freeReplyObject(reply);
while(redisGetReply(context,(void *)reply) REDIS_OK) {// consume messagefreeReplyObject(reply);
}释放资源
/* 释放一个响应对象 */
void freeReplyObject(void *reply)/* 释放上下文自动断开连接 */
void redisFree(redisContext *c);3.异步API说明
建立连接
调用异步建连接口返回redis异步上下文 redisAsyncContext 注意: redisAsyncContext 不是线程安全的。此外使用异步调用还需要设置回调函数。
/* 建立异步连接 */
redisAsyncContext *redisAsyncConnect(const char *ip, int port);
/* 建立带参数选项的异步连接 */
redisAsyncContext *redisAsyncConnectWithOptions(const redisOptions *options);/* 回调函数指针 */
typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status);
typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status);
typedef void (redisConnectCallbackNC)(struct redisAsyncContext *, int status);
typedef void(redisTimerCallback)(void *timer, void *privdata);/* 设置异步回调函数 */
int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn);
int redisAsyncSetConnectCallbackNC(redisAsyncContext *ac, redisConnectCallbackNC *fn);
int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);示例
void appConnect(myAppData *appData)
{redisAsyncContext *c redisAsyncConnect(127.0.0.1, 6379);if (c-err) {printf(Error: %s\n, c-errstr);// handle errorredisAsyncFree(c);c NULL;} else {appData-context c;appData-connecting 1;c-data appData; /* store application pointer for the callbacks */redisAsyncSetConnectCallback(c, appOnConnect);redisAsyncSetDisconnectCallback(c, appOnDisconnect);}
}void appOnConnect(redisAsyncContext *c, int status)
{myAppData *appData (myAppData*)c-data; /* get my application specific context*/appData-connecting 0;if (status REDIS_OK) {appData-connected 1;} else {appData-connected 0;appData-err c-err;appData-context NULL; /* avoid stale pointer when callback returns */}appAttemptReconnect();
}void appOnDisconnect(redisAsyncContext *c, int status)
{myAppData *appData (myAppData*)c-data; /* get my application specific context*/appData-connected 0;appData-err c-err;appData-context NULL; /* avoid stale pointer when callback returns */if (status REDIS_OK) {appNotifyDisconnectCompleted(mydata);} else {appNotifyUnexpectedDisconnect(mydata);appAttemptReconnect();}
}发送命令
/* Reply回调函数 */
typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*);/* 异步发送操作命令 */
int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...);
int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen);注意当命令执行完成发生 Reply回复回调时回调数据只会在回调函数中有效一旦回调函数结束指针指向的数据就无效了 释放资源
/* 释放连接 */
void redisAsyncDisconnect(redisAsyncContext *ac);/* 释放异步上下文 */
void redisAsyncFree(redisAsyncContext *ac);结束语
参考
GitHub上的hiredis项目的 README文档
最后忍不住想吐槽一下C的开源项目真的做的不如Python、java好。 Redis作为当前最热门的开源项目之一hiredis也有很多的用户。然而hiredis的对外接口也没有很好的函数说明。 在使用过程中一个很大的问题即当传入的参数有多个时参数的含义基本靠猜比如redisCommandArgv、函数的返回值使用 void* 后很难知晓其含义比如redisCommand
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/88430.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!