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