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];

休息一下子。

相关文章
相关标签/搜索