欲知後事如何,且讓我慢慢道來。 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];
休息一下子。