main函数基本流程:
大致代码如下:
int main(int argc, char **argv) {
int firstarg;
char **argvcopy;
struct redisCommand *rc;
//设置基本配置
config.hostip = "127.0.0.1";
config.hostport = 6379;
....
//......基本配置代码
//格式化命令
firstarg = parseOptions(argc,argv);//格式化命令行参数,返回参数为执行参数的个数
if (config.auth != NULL) {//有权限
...
有权限的操作
}
//启动时没有参数或 进入交互模式 例如./redis-cli
if (argc == 0 || config.interactive == 1) repl();
//将后面的未执行的命令拷贝到argvcopy
//例如./redis-cli set name wwz
argvcopy = convertToSds(argc, argv);
//结果为argvcopy[0] = set argvcopy[1] = name argvcopy[2] = wwz
if ((rc = lookupCommand(argv[0])) != NULL) {//命令是否存在
if (rc->arity > 0 && argc == rc->arity-1) {//这个时arity是正数且合法长度的
sds lastarg = readArgFromStdin();
argvcopy[argc] = lastarg;//再来一个结束符
argc++;
}
}
//进行下一条语句完成后,结束客户端程序。
return cliSendCommand(argc, argvcopy, config.repeat);
}
客户端发送命令函数cliSendCommand
/*cliSendCommand 客户端发送命令
* @param int argc 参数个数
* @param char **argv sds字符串数组
* @param int repeat 重复次数
* @return int 失败为1 成功为0
*/
static int cliSendCommand(int argc, char **argv, int repeat) {
//检查命令是否合法,连接客户端与服务器
.....
//选择数据库
retval = selectDb(fd);
...
while(repeat--) {//一般都是1 意思为循环一次 执行一次命令
//以发送命令多元为例
cmd = sdsempty();
if (rc->flags & REDIS_CMD_MULTIBULK) {
//命令;mset name wwz age 21
cmd = sdscatprintf(cmd,"*%d\r\n",argc);//*5\r\n
for (j = 0; j < argc; j++) {
cmd = sdscatprintf(cmd,"$%lu\r\n",
(unsigned long)sdslen(argv[j]));
cmd = sdscatlen(cmd,argv[j],sdslen(argv[j]));
cmd = sdscatlen(cmd,"\r\n",2);
}
//*5\r\n$4mset\r\n$4name\r\n$3wwz\r\n$3age$221\r\n
}
....
//发送--------
anetWrite(fd,cmd,sdslen(cmd));
sdsfree(cmd);
//读取,判断类型再进行进一步读取,注意cliReadMultiBulkReply[多元的]的每一个元素都调用了cliReadBulkReply(就是类型为$的)
retval = cliReadReply(fd);
if (retval) {
return retval;
}
}
return 0;
}