简体   繁体   English

epoll_wait 不等待超时时间

[英]epoll_wait does not wait for the timeout period

I am trying to create a non-blocking connect with epoll.我正在尝试创建一个与 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 .我仍在学习 epoll,所以我尝试使用此示例中提到的代码 - How to code an epoll based sockets client in C。

I just modified the timeout and make the event as EPOLLOUT.我刚刚修改了超时并将事件设置为 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.端口 20000 上没有运行服务器进程。套接字仍然能够连接事件 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.这是一种特殊情况,因为可以立即建立连接,因此极不可能返回EINPROGRESS As the connection is established, the file descriptor becomes writable, and epoll_wait returns that event, so you are all settled to proceed.随着连接的建立,文件描述符变为可写, epoll_wait返回该事件,所以你已经准备好继续了。 It would wait your timeout before erroring out if 3-way-handshake with a remote host took longer than 100 seconds.如果与远程主机的 3 次握手花费的时间超过 100 秒,它会在出错之前等待您的超时。

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.main()返回后,您必须fork()或使用线程离开进程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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