listenToPort函数会对所有配置需要监听的ip地址和端口调用_anetTcpServer函数(anet.c), _anetTcpServer函数源码如下,1-17行建立socket套接字s,23行调用函数anetListen完成服务端socket的bind和listen。
1 static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog)
2 {
3 int s = -1, rv;
4 char _port[6]; /* strlen("65535") */
5 struct addrinfo hints, *servinfo, *p;
6 snprintf(_port,6,"%d",port);
7 memset(&hints,0,sizeof(hints));
8 hints.ai_family = af;
9 hints.ai_socktype = SOCK_STREAM;
10 hints.ai_flags = AI_PASSIVE; /* No effect if bindaddr != NULL */
11
12 if ((rv = getaddrinfo(bindaddr,_port,&hints,&servinfo)) != 0) {
13 anetSetError(err, "%s", gai_strerror(rv));
14 return ANET_ERR;
15 }
16 for (p = servinfo; p != NULL; p = p->ai_next) {
17 if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)
18 continue;
19
20 if (af == AF_INET6 && anetV6Only(err,s) == ANET_ERR) goto error;
21 if (anetSetReuseAddr(err,s) == ANET_ERR) goto error;
22 //anetListen调用listen和bind
23 if (anetListen(err,s,p->ai_addr,p->ai_addrlen,backlog) == ANET_ERR) s = ANET_ERR;
24 goto end;
25 }
26 if (p == NULL) {
27 anetSetError(err, "unable to bind socket, errno: %d", errno);
28 goto error;
29 }
30
31 error:
32 if (s != -1) close(s);
33 s = ANET_ERR;
34 end:
35 freeaddrinfo(servinfo);
36 return s;
37 }
1 static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len, int backlog) {
2 if (bind(s,sa,len) == -1) {
3 anetSetError(err, "bind: %s", strerror(errno));
4 close(s);
5 return ANET_ERR;
6 }
7
8 if (listen(s, backlog) == -1) {
9 anetSetError(err, "listen: %s", strerror(errno));
10 close(s);
11 return ANET_ERR;
12 }
13 return ANET_OK;
14 }
在分析aeCreateTimeEvent和aeCreateFileEvent函数之前,先给出server中的aeEventLoop类型变量el结构体定义(ae.h):
/* File event structure */
//文件事件结构体
typedef struct aeFileEvent {
////读或者写,也用于标识该事件结构体是否正在使用
int mask; /* one of AE_(READABLE|WRITABLE|BARRIER) */
//读事件的处理函数
aeFileProc *rfileProc;
//写事件的处理函数
aeFileProc *wfileProc;
//传递给上述两个函数的数据
void *clientData;
} aeFileEvent;
/* Time event structure */
//时间事件
typedef struct aeTimeEvent {
//时间事件标识符,用于唯一标识该时间事件,并且用于删除时间事件
long long id; /* time event identifier. */
long when_sec; /* seconds */
long when_ms; /* milliseconds */
//事件对应的处理程序
aeTimeProc *timeProc;
//时间事件的最后一次处理程序,若已设置,则删除时间事件时会被调用
aeEventFinalizerProc *finalizerProc;
void *clientData;
struct aeTimeEvent *prev;
struct aeTimeEvent *next;
} aeTimeEvent;
/* A fired event */
//用于保存已触发的事件
typedef struct aeFiredEvent {
int fd;