networking的代码主要是针对client的命令进行处理,主要是实现三个功能:client连接的管理;解析client的请求;发送回复内容给client。
一、client连接的管理
进行连接的接收,并创建client结构体,完成内部属性的初始化,事件回调函数的设置。
void acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
……
while(max--) {
cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport);
if (cfd == ANET_ERR) {
……
return;
}
serverLog(LL_VERBOSE,"Accepted %s:%d", cip, cport);
acceptCommonHandler(cfd,0,cip);
}
}
static void acceptCommonHandler(int fd, int flags, char *ip) {
client *c;//连接建立创建client结构体
if ((c = createClient(fd)) == NULL) {
close(fd); /* May be already closed, just ignore errors */
return;
}
//client连接个数超过server.maxclients,将被拒绝,释放client
if (listLength(server.clients) > server.maxclients) {
……
server.stat_rejected_conn++;
freeClient(c);
return;
}
……
server.stat_numconnections++;
c->flags |= flags;
}
client *createClient(int fd) {
client *c = zmalloc(sizeof(client));
//设置socket fd的选项和可读事件回调函数readQueryFromClient
if (fd != -1) {
anetNonBlock(NULL,fd);
anetEnableTcpNoDelay(NULL,fd);
if (server.tcpkeepalive)
anetKeepAlive(NULL,fd,server.tcpkeepalive);
if (aeCreateFileEvent(server.el,fd,AE_READABLE,
readQueryFromClient, c) == AE_ERR)
{
……
}
}
selectDb(c,0);
……//初始化client内部属性
listSetFreeMethod(c->pubsub_patterns,decrRefCountVoid);
listSetMatchMethod(c->pubsub_patterns,listMatchObjects);
if (fd != -1) listAddNodeTail(server.clients,c);
initClientMultiState(c);
return c;
}
二、解析client的请求
在统一的请求协议中, 所有发送至 Redis 服务器的参数都是二进制安全(binary safe)的。
协议的一般格式如下: