Search code examples
ctcpsocketserver

Blocking accept


I'm programing a TCP/IP Socketserver.

My problem is, that my accept call is blocking and not accepting any new incomming connections when I (for example) telnet my server and do not send any data.

When I'm sending anything or quit the telnet accept stops blocking, I can handle the sent data and accept starts to accepting new incomming connections.

main() {
   socket = bind_listen();

   while(1) {
       user_socket = accept(socket);
       ssl = SSL_new(ctx);
       SSL_set_fd(ssl, user_socket);
       SSL_accept(ssl);

       event.data.fd = user_socket;
       event.events = EPOLLIN | EPOLLONESHOT;

       epoll_proof = epoll_ctl(poll_fd, EPOLL_CTL_ADD, user_socket, &event);
   }
}

There are several threads which epoll_wait() and handle data. Any idea? Thanks!


Solution

  • First off, you should poll the listening file descriptor (with select, poll or epoll/kqueue) and only call accept if it's ready to read.

    Second, and more specifically, if you're going for edge-triggered epoll, you need to set your socket into non-blocking mode first. Then, when you're told that it's ready to read, you need to call accept in a loop until you return -1 with error EAGAIN or EWOULDBLOCK -- there may be multiple connection requests waiting at once, and edge-triggered polling only alerts you on state changes, so you need to drain the socket.

    In a really, really naive fashion you could also do away with the polling and only work with non-blocking sockets, either in a busy loop or in a loop with a sort of sleep. But that's utterly wasteful, and doesn't buy you anything compared to the proper epoll/kqueue solution (or whatever polling mechanism your platform supplies).