redis源码阅读3----客户端连接过程
本章主要讨论在client连接到server时。server在ae过程中是如何处理的。
主要讨论的是接口函数。
大家可以把断点打在networking/acceptTcpHandler()下
以上函数在ae.c下如下部分调用:
if (!invert && fe->mask & mask & AE_READABLE) { fe->rfileProc(eventLoop,fd,fe->clientData,mask); #此处 fired++; fe = &eventLoop->events[fd]; /* Refresh in case of resize. */ } rfileProc是在ae.h中被定义的 typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask); 然后acceptTcpHandler则是在main函数中,初始化redis时注册的。 在server.c下 if (createSocketAcceptHandler(&server.ipfd, acceptTcpHandler) != C_OK) { serverPanic("Unrecoverable error creating TCP socket accept handler."); acceptTcpHandler()下最重要的调用是 anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport); 其中会调用 anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len); 进入anetGenericAccept,你就会发现,最底层的unix调用--->accept accept之后,返回到anetTcpAccept。然后他会把对端ip和端口单独存一下到cport和cip。 最后就是调用acceptCommonHandler------------>connCreateAcceptedSocket----->connCreateSocket------->zcalloc检查是否有足够内存给新连接用。 分配内存失败了还会调用zmalloc_oom_handler(size) 然后检查客户端最大连接数有没有超。 为什么检查是在accept之后的。这是官方给出的解释: /* Limit the number of connections we take at the same time. * * Admission control will happen before a client is created and connAccept() * called, because we don't want to even start transport-level negotiation * if rejected. */ 最后就是调用createClient(connection *conn),创建连接。(叫创建连接可能不太合适,应该是初始化连接,能走到这一步,tcp已经建立好连接了) 整个流程就完毕了。