How to accept client requests and call processing functions

Source: Internet
Author: User
The previous article outlines the redis startup process. This article focuses on how redis accepts client requests and calls processing functions to execute commands. In the previous article, the initServer () function calls the anetTcpServer and anetUnixServer functions to create a listener for tcp ports and unix domain sockets.

The previous article outlines the redis startup process. This article focuses on how redis accepts client requests and calls processing functions to execute commands. In the previous article, the initServer () function calls the anetTcpServer and anetUnixServer functions to create a listener for tcp ports and unix domain sockets.

The previous article outlines the redis startup process. This article focuses on how redis accepts client requests and calls processing functions to execute commands.

In the previous article, the U.S. server said that in the initServer () function, it will call the anetTcpServer and anetUnixServer functions to create a listener for tcp ports and unix domain sockets, first, we will focus on the implementation of these two functions.

Int anetTcpServer (char * err, int port, char * bindaddr) {int s; struct sockaddr_in sa; if (s = anetCreateSocket (err, AF_INET) = ANET_ERR) return ANET_ERR; memset (& sa, 0, sizeof (sa); sa. sin_family = AF_INET; sa. sin_port = htons (port); sa. sin_addr.s_addr = htonl (INADDR_ANY); if (bindaddr & inet_aton (bindaddr, & sa. sin_addr) = 0) {anetSetError (err,); close (s); return ANET_ERR;} if (anetListen (err, s, (struct sockaddr *) & sa, sizeof (sa) = ANET_ERR) return ANET_ERR; return s ;}

From the code, we can see that, first call anetCreateSocket () to create a socket and re-value it to s, then initialize the addr_in struct of sa, and set the port and address to be listened, and the address family, and then call the anetListen () function to bind the address and listen to the port. after the work is completed, the anetCreateSocket function returns, the website space, and copies the created socket to the server. ipfd. Note that the work done in the anetUnixServer () function is similar to anetCreateSocket, but it is only a bound unix socket.

Next, we call this function in the initServer function: aeCreateFileEvent. Here we will focus on the first function and the second function.

If (server. ipfd> 0 & aeCreateFileEvent (server. el, server. ipfd, AE _READABLE, acceptTcpHandler, NULL) = AE _ERR) oom (); if (server. sofd> 0 & aeCreateFileEvent (server. el, server. sofd, AE _READABLE, acceptUnixHandler, NULL) = AE _ERR) oom ();

First, extract the acFileEvent corresponding to the current fd from the eventLoop event aeFileEvent array, mainly to set the corresponding event processing function for it below; that is, the input mask is used to determine the type of events.

Int aeCreateFileEvent (aeEventLoop * eventLoop, int fd, int mask, aeFileProc * proc, void * clientData) {if (fd> = AE _SETSIZE) return AE _ERR; aeFileEvent * fe = & eventLoop-> events [fd]; if (aeApiAddEvent (eventLoop, fd, mask) =-1) return AE _ERR; fe-> mask | = mask; if (mask & AE _READABLE) fe-> rfileProc = proc; if (mask & AE _WRITABLE) fe-> wfileProc = proc; fe-> clientData = clientData; if (fd> eventLoop-> maxfd) eventLoop-> maxfd = fd; return AE _ OK ;}

Then, call the acApiEvent event to register the function:

Static int aeApiAddEvent (aeEventLoop * eventLoop, int fd, int mask) {aeApiState * state = eventLoop-> apidata; struct epoll_event ee;/* If the fd was already monitored for some event, we need a MOD * operation. otherwise we need an ADD operation. */int op = eventLoop-> events [fd]. mask = AE _NONE? EPOLL_CTL_ADD: EPOLL_CTL_MOD; ee. events = 0; mask | = eventLoop-> events [fd]. mask; (mask & AE _READABLE) ee. events | = EPOLLIN; if (mask & AE _WRITABLE) ee. events | = EPOLLOUT; ee. data. u64 = ee. data. fd = fd; if (epoll_ctl (state-> epfd, op, fd, & ee) =-1) return-1; return 0 ;}

We can see that this function mainly calls epoll_ctl (state-> epfd, op, fd, & ee) register the current fd settings with the relevant events to the epoll handle returned by epoll_create. Because we registered the AE _READABLE event here, when this fd (that is, the socket of the redis listening port) has data readable (here I understand that the client connection arrives), the website space, the corresponding event processing function will be triggered. The event processing function here is acceptTcpHandler.


Let's take a look at the acceptTcpHandler function:

This function first calls anetTcpAccept to obtain the socket fd (the fd returned by the actual call: accept (s, sa, len) function) connected to redis from the client, and then calls the acceptCommonHandler () function, this function calls createClient () to create a redisClient * c instance. If the total number of connections of the current redis server does not exceed the maximum value, the stat_numconnections recorded in the global variable server is added to 1; if this parameter is exceeded, the function returns an error message from the client and releases the redisClient instance.

Void acceptTcpHandler (aeEventLoop * el, int fd, void * privdata, int mask) {int cport, cfd; char cip [128]; REDIS_NOTUSED (el); REDIS_NOTUSED (mask ); REDIS_NOTUSED (privdata); cfd = anetTcpAccept (server. neterr, fd, cip, & cport); if (cfd = AE _ERR) {redisLog (REDIS_WARNING, server. neterr); return;} redisLog (REDIS_VERBOSE, cip, cport); acceptCommonHandler (cfd );}

The createClient function is analyzed as follows:

RedisClient * createClient (int fd) {redisClient * c = zmalloc (sizeof (redisClient); c-> bufpos = 0; anetNonBlock (NULL, fd); anetTcpNoDelay (NULL, fd); if (aeCreateFileEvent (server. el, fd, AE _READABLE, readQueryFromClient, c) = AE _ERR) {close (fd); zfree (c); return NULL;} selectDb (c, 0 ); c-> fd = fd; c-> querybuf = sdsempty (); c-> reqtype = 0; c-> argc = 0; c-> argv = NULL; c-> cmd = c-> lastcmd = NULL; c-> multibulklen = 0; c-> bulklen =-1; c-> sentlen = 0; c-> flags = 0; c-> lastinteraction = time (NULL); c-> authenticated = 0; c-> replstate = REDIS_REPL_NONE; c-> slave_listening_port = 0; c-> reply = listCreate (); c-> reply_bytes = 0; listSetFreeMethod (c-> reply, decrRefCount); listSetDupMethod (c-> reply, dupClientReplyValue ); c-> bpop. keys = NULL; c-> bpop. count = 0; c-> bpop. timeout = 0; c-> bpop.tar get = NULL; c-> io_keys = listCreate (); c-> watched_keys = listCreate (); listSetFreeMethod (c-> io_keys, decrRefCount ); c-> pubsub_channels = dictCreate (& setDictType, NULL); c-> pubsub_patterns = listCreate (); publish (c-> pubsub_patterns, decrRefCount); listSetMatchMethod (c-> Publish, listMatchObjects); listAddNodeTail (server. clients, c); initClientMultiState (c); return c ;}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.