简体   繁体   中英

epoll_wait does not wait for the timeout period

I am trying to create a non-blocking connect with epoll. I am still learning epoll so I was giving a try with the code mentioned in this example - How to code an epoll based sockets client in C .

I just modified the timeout and make the event as EPOLLOUT.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 20000
#define SERVER "127.0.0.1"
#define MAXBUF 1024
#define MAX_EPOLL_EVENTS 64

int main() {
    int sockfd;
    struct sockaddr_in dest;
    char buffer[MAXBUF];
    struct epoll_event events[MAX_EPOLL_EVENTS];
    int i, num_ready;

    /*---Open socket for streaming---*/
    if ( (sockfd = socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, 0)) < 0 ) {
        perror("Socket");
        exit(errno);
    }

    /*---Add socket to epoll---*/
    int epfd = epoll_create(1);
    struct epoll_event event;
    event.events = EPOLLOUT; // Cann append "|EPOLLOUT" for write events as well
    event.data.fd = sockfd;
    epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event);

    /*---Initialize server address/port struct---*/
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
        dest.sin_port = htons(PORT);
    if ( inet_pton(AF_INET, SERVER, &dest.sin_addr.s_addr) == 0 ) {
        perror(SERVER);
        exit(errno);
    }

    /*---Connect to server---*/
    if ( connect(sockfd, (struct sockaddr*)&dest, sizeof(dest)) != 0 ) {
        if(errno != EINPROGRESS) {
            perror("Connect ");
            exit(errno);
        }
    }

    /*---Wait for socket connect to complete---*/
    num_ready = epoll_wait(epfd, events, MAX_EPOLL_EVENTS, 100000/*timeout*/);
    for(i = 0; i < num_ready; i++) {
        if(events[i].events & EPOLLOUT) {
            printf("Socket %d connected\n", events[i].data.fd);
        }
    }

    /*---Wait for data---*/
    num_ready = epoll_wait(epfd, events, MAX_EPOLL_EVENTS, 100000);
    for(i = 0; i < num_ready; i++) {
        if(events[i].events & EPOLLOUT) {
            printf("Socket %d got some data\n", events[i].data.fd);
            //bzero(buffer, MAXBUF);
            //recv(sockfd, buffer, sizeof(buffer), 0);
            //printf("Received: %s", buffer);
        }
    }

    close(sockfd);
    return 0;
}

Result:

[root@test-vm socket_prgm]# ./test_epoll_so.o 
Socket 3 connected
Socket 3 got some data

Two things I am observing with the above program:

  1. There is no server process running on the port 20000. The socket was still able to connect for the event EPOLLOUT.
  2. The timeout period does not work at all. The script executes immediately.

Am I missing something obvious here? Thank you.

I think the obvious is indeed missed:

2.The timeout period does not work at all. The script executes immediately.

It executes immediately because you connect to the local host. This is a particular scenario when EINPROGRESS is highly unlikely to be returned because the connection can be established immediately. As the connection is established, the file descriptor becomes writable, and epoll_wait returns that event, so you are all settled to proceed. It would wait your timeout before erroring out if 3-way-handshake with a remote host took longer than 100 seconds.

1. There is no server process running on the port 20000. The socket was still able to connect for the event EPOLLOUT.

This is your miss: there's nothing in your code making it a background process. You have to fork() or use threads to leave a process after your main() returns.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM