struct evconnlistener * evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, const struct sockaddr *sa, int socklen) { /* 共7个入参: @base --base指针; @cb --监听回调,当监听的事件触发时执行; @ptr --一个空指针类型,这里是将base指针强转后传入; @flags --监听标志(选项),通常会设置地址复用等标志; @backlog --连接队列最大长度,填"-1"默认128; @sa --服务端socket地址; @socklen --地址长度; */ //1.先准备一个监听器指针 struct evconnlistener *listener; /* 2.创建套接字: --设置协议族 --设置协议名和非阻塞 */ evutil_socket_t fd; int on = 1; int family = sa ? sa->sa_family : AF_UNSPEC; int socktype = SOCK_STREAM | EVUTIL_SOCK_NONBLOCK;//TCP,非阻塞 if (backlog == 0) return NULL; //内部调用exec()前关闭此文件描述符; if (flags & LEV_OPT_CLOSE_ON_EXEC) socktype |= EVUTIL_SOCK_CLOEXEC; fd = evutil_socket_(family, socktype, 0); if (fd == -1) return NULL; //3.给套接字设置心跳检测 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on))<0) goto err; //4.给套接字设置地址复用 if (flags & LEV_OPT_REUSEABLE) { if (evutil_make_listen_socket_reuseable(fd) < 0) goto err; } //5.给套接字设置端口复用 if (flags & LEV_OPT_REUSEABLE_PORT) { if (evutil_make_listen_socket_reuseable_port(fd) < 0) goto err; } if (flags & LEV_OPT_DEFERRED_ACCEPT) { if (evutil_make_tcp_listen_socket_deferred(fd) < 0) goto err; } if (flags & LEV_OPT_BIND_IPV6ONLY) { if (evutil_make_listen_socket_ipv6only(fd) < 0) goto err; } //6.给套接字绑定地址 if (sa) { if (bind(fd, sa, socklen)<0) goto err; } /*7. 入参:event_base指针、监听回调、event_base的空指针类型、监听队列长度、已初始化的套接字; 返回:一个可用的“监听器”指针; */ listener = evconnlistener_new(base, cb, ptr, flags, backlog, fd); if (!listener) goto err; return listener; err: evutil_closesocket(fd); return NULL; }