Search code examples
linuxsocketstcpdumpepoll

socket fin after syn ack on centos 7


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.

[syn]

[syn,ack]

[ack]

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

here is my tcpdump result. enter image description here


Solution

  • 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.