欲知后事如何,且让我慢慢道来。 node
如今讲到了函数acceptTcpHandler。咱们来跟进去看原理。 redis
~~~~~~~~~~~~~~~ api
int cport;//定义整型变量
int cfd;//定义整型变量
char cip[REDIS_IP_STR_LEN]; tcp
REDIS_NOTUSED(el);
REDIS_NOTUSED(mask);
REDIS_NOTUSED(privdata); 函数
//没用 .net
而后是代码 日志
cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport);
if (cfd == AE_ERR) {
redisLog(REDIS_WARNING,"Accepting client connection: %s", server.neterr);
return;
} server
那么咱们开始研究函数 anetTcpAccept。 blog
~~~~~~~~~~~~~~~跟进去看代码anetTcpAccept ip
这个函数调用了函数anetGenericAccept
咱们如今来分析anetGenericAccept函数。
代码以下:
static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len)
{
//自定义检查点: 1 2 3
int fd;//定义整型变量
//自定义检查点: 1 2 3
while(1)
{
//循环处理
//自定义检查点: 1 2 3
fd = accept(s,sa,len);
if (fd == -1)
{
if (errno == EINTR)
continue;
else
{
anetSetError(err, "accept: %s", strerror(errno));
return ANET_ERR;
}
}
break;
}
return fd;
//自定义检查点: 1 2 3
}
也就是说,仍是经过了accept API来接受一个客户的链接,同时对accept的中断进行处理。
好,目前返回了一个链接句柄,返回。
让咱们回到anetTcpAccept函数继续往下执行。
if (sa.ss_family == AF_INET)这里是//填写客户信息IP+端口
整个函数返回。
~~~~~~~~~~
如今咱们又回到函数acceptTcpHandler中。
redisLog(REDIS_VERBOSE,"Accepted %s:%d", cip, cport);记录日志。
最后一行代码是: acceptCommonHandler(cfd,0);,这个函数调用了createClient
咱们来研究createClient函数。
~~~~~~~~~~~~~~~~~~
anetNonBlock(NULL,fd);//设置fd为非阻塞
anetEnableTcpNoDelay(NULL,fd);//设置nodelay
关于nodelay的意义,请参考http://blog.csdn.net/shaobingj126/article/details/6758707
if (server.tcpkeepalive)
{
anetKeepAlive(NULL,fd,server.tcpkeepalive);
}
//这个不执行。
~~~~~~~~~~~~~~~~~~~~~~~~~~
if (
aeCreateFileEvent(
server.el,
fd,
AE_READABLE,
readQueryFromClient,
c) == AE_ERR
)
{
close(fd);
zfree(c);
return NULL;
}
这个函数的做用是把以前的客户链接句柄加入到server.el->apidata.epfd中去。
后面的函数是:selectDb
这个是执行c->db = &server.db[0];
休息一下子。