Redis源碼分析系列十:acceptTcpHandler

欲知後事如何,且讓我慢慢道來。 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)
 {
        struct sockaddr_in *s = (struct sockaddr_in *)&sa;
        if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len);
        if (port) *port = ntohs(s->sin_port);
    }
 else
 {
        struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa;
        if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len);
        if (port) *port = ntohs(s->sin6_port);
    }

這裏是//填寫客戶信息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];

休息一下子。

相關文章
相關標籤/搜索