当socket设置成非阻塞时,并且将EPOLLOUT事件通过epoll_ctl添加时,可写事件总是会触发,可以通过写代码来验证
代码如下:
#include <sys/socket.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#define SERV_PORT 10000
#define MAX_EVENTS 10
#define LEN 2
int main(int argc, char **argv)
{
if (argc != 2) {
perror("usage:exe port\n");
return -1;
}
struct sockaddr_in servaddr;
int sockfd;
memset(&servaddr, 0x00, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[1]));
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket error");
exit(-1);
}
if (bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) {
perror("bind error");
close(sockfd);
exit(-1);
}
if (listen(sockfd, 3) == -1) {
perror("listen error");
close(sockfd);
exit(-1);
}
int epollfd = epoll_create(MAX_EVENTS);
if (epollfd == -1) {
perror("epoll_create error");
close(sockfd);
exit(-1);
}
struct epoll_event ev, events[MAX_EVENTS];
ev.events = EPOLLIN;
ev.data.fd = sockfd;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev) == -1) {
perror("epoll_ctl error");
exit(-1);
}
int nfds, connfd;
for (;;) {
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
if (nfds == -1) {
perror("epoll_wait error");
exit(-1);
}
int i;
for (i = 0; i < nfds; i++) {
if (events[i].data.fd == sockfd) {
connfd = accept(sockfd, NULL, NULL);
printf("connfd=%d\n", connfd);
if (connfd == -1) {
perror("accept error");
exit(-1);
}
int flag;
flag = fcntl(connfd, F_GETFL, 0);
fcntl(connfd, F_SETFL, flag & ~O_NONBLOCK);
ev.events = EPOLLOUT;
ev.data.fd = connfd;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &ev) == -1) {
perror("epoll_ctl error");
exit(-1);
}
} else {
/*
char buf[LEN];
int n = read(events[i].data.fd, buf, LEN);
buf[n] = 0;
printf("buf=%s\n", buf);
*/
if (events[i].events & EPOLLOUT) {
printf("fd=%d\n", events[i].data.fd);
}
}
}
}
}
当监听到有连接到来时,接收连接,并且将连接设置成非阻塞,添加EPOLLOUT事件,这时会一直打印fd=5
输出为
可以像libevent那样,当有数据要写时,才将描述符fd添加进去,数据写完之后,再将fd删除