I write a tcp server with epoll, it works right on Ubuntu, but strange things happens on CentOS7 occasional.
client a try to connect to server b, the connection was build, the port for client is 59298, port for server is 8802, and the socketfd at server is 16.
at the mean time the server read event with return value zero, with the same sockfd, which is 16, JUST the same as the connection build before, tell the connection between a and b was closed. server send a package of [rst,ack] to client with different port, which is 59191. why this happens ? is it a bug of centos kernel?
my code is very similar to this below.
#define MAX_EVENTS 10
struct epoll_event ev, events[MAX_EVENTS];
int listen_sock, conn_sock, nfds, epollfd;
/* Set up listening socket, 'listen_sock' (socket(),
bind(), listen()) */
epollfd = epoll_create(10);
if (epollfd == -1) {
perror("epoll_create");
exit(EXIT_FAILURE);
}
ev.events = EPOLLIN;
ev.data.fd = listen_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {
perror("epoll_ctl: listen_sock");
exit(EXIT_FAILURE);
}
for (;;) {
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
if (nfds == -1) {
perror("epoll_pwait");
exit(EXIT_FAILURE);
}
for (n = 0; n < nfds; ++n) {
if (events[n].data.fd == listen_sock) {
conn_sock = accept(listen_sock,
(struct sockaddr *) &local, &addrlen);
if (conn_sock == -1) {
perror("accept");
exit(EXIT_FAILURE);
}
setnonblocking(conn_sock);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = conn_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,
&ev) == -1) {
perror("epoll_ctl: conn_sock");
exit(EXIT_FAILURE);
}
} else {
do_use_fd(events[n].data.fd);
}
}
}
I got the reason after read man epoll. it happens due to unsuitable code.
epoll_ctl(epollfd_, EPOLL_CTL_DEL, sockfd, &ev)
it seems there is few correct usage sample about epoll on github.