el,fd,AE_READABLE,
readQueryFromClient, c) == AE_ERR)
{
close(fd);
zfree(c);
return NULL;
}
}
selectDb(c,0);//默认选择第0个db, db.c
c->fd = fd;//文件描述符
c->name = NULL;
c->bufpos = 0;//将指令结果发送给客户端的字符串长度
c->querybuf = sdsempty();//请求字符串初始化
c->querybuf_peak = 0;//请求字符串顶峰时的长度值
c->reqtype = 0;//请求类型
c->argc = 0;//参数个数
c->argv = NULL;//参数内容
c->cmd = c->lastcmd = NULL;//操作指令
c->multibulklen = 0;//块个数
c->bulklen = -1;//每个块的长度
c->sentlen = 0;
c->flags = 0;//客户类型的标记,比较重要
c->ctime = c->lastinteraction = server.unixtime;
c->authenticated = 0;
c->replstate = REDIS_REPL_NONE;
c->reploff = 0;
c->repl_ack_off = 0;
c->repl_ack_time = 0;
c->slave_listening_port = 0;
c->reply = listCreate();//存放服务器应答的数据
c->reply_bytes = 0;
c->obuf_soft_limit_reached_time = 0;
listSetFreeMethod(c->reply,decrRefCountVoid);
listSetDupMethod(c->reply,dupClientReplyValue);
c->bpop.keys = dictCreate(&setDictType,NULL);//下面三个参数在list数据阻塞操作时使用
c->bpop.timeout = 0;
c->bpop.target = NULL;
c->io_keys = listCreate();
c->watched_keys = listCreate();//事务命令CAS中使用
listSetFreeMethod(c->io_keys,decrRefCountVoid);
c->pubsub_channels = dictCreate(&setDictType,NULL);
c->pubsub_patterns = listCreate();
listSetFreeMethod(c->pubsub_patterns,decrRefCountVoid);
listSetMatchMethod(c->pubsub_patterns,listMatchObjects);
// 如果不是伪客户端,那么将客户端加入到服务器客户端列表中
if (fd != -1) listAddNodeTail(server.clients,c);//添加到server的clients链表
initClientMultiState(c);//初始化事务指令状态
return c;
}
客户端的请求指令字符串始终存放在querybuf中,在对querybuf解析后,将指令参数的个数存放在argc中,具体的指令参数存放在argv中;但是服务器应答的结果有两种存储方式:buf字符串、reply列表。
readQueryFromClient函数
readQueryFromClient函数用来读取客户端的请求命令行数据,并调用processInputBuffer函数依照redis通讯协议对数据进行解析。服务器使用最原始的read函数来读取客户端发送来的请求命令,并将字符串存储在querybuf中,根据需要对querybuf进行扩展。
void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
redisClient *c = (redisClient*) privdata;
int nread, readlen;
size_t qblen;
REDIS_NOTUSED(el);
REDIS_NOTUSED(mask);
server.current_client = c;
readlen = REDIS_IOBUF_LEN; //1024 * 16
/* If this is a multi bulk request, and we are processing a bulk reply
* that is large enough, try to maximize the probability that the query
* buffer contains exactly the SDS string representing the object, even
* at the risk of requiring more read(2) calls. This way the function
* processMultiBulkBuffer() can avoid copying buffers to create the
* Redis Object representing the argument. */
if (c->reqtype == REDIS_REQ_MULTIBULK && c->multibulklen && c->bulklen != -1
&& c->bulklen >= REDIS_MBULK_BIG_ARG)
{
int remaining = (unsigned)(c->bulklen+2)-sdslen(c->querybuf);
if (remaining < readlen) readlen = remaining;
}
qblen = sdslen(c->querybuf);
if (c->querybuf_peak < qblen) c->querybuf_peak = qblen;
//对querybuf的空间进行扩展
c->querybuf = sdsMakeRoomFor(c->querybuf, readlen);
//读取客户端发来的操作指令
nread = read(fd, c->querybuf+qblen, readlen);
if (nread == -1) {
if (errno == EAGAIN) {
nread = 0;
} else {
redisLog(REDIS_VERBOSE, "Reading from client: %s",strerror(errno));
freeClient(c);
return;
}
} else if (nread == 0) {
redisLog(REDIS_VERBOSE, "Client closed connection");
freeClient(c);
return;
}
if (nread) {
//改变querybuf的实际长度和空闲长度,len += nread, free -= nread;
sdsIncrLen(c->querybuf,nread);
c->lastinteraction = server.unixtime;
if (c