标题:有大佬懂epoll吗,帮忙看一下
只看楼主
星泪成寒
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:6
帖 子:75
专家分:539
注 册:2013-5-19
结帖率:100%
已结贴  问题点数:20 回复次数:2 
有大佬懂epoll吗,帮忙看一下
建了一个监听8088端口的http服务器,
我把监听socket 加入epoll, 发起http请求后 触发了,
accept后我把 连接socket加入epoll(读事件), 也触发了,但是recv() 的errno 总是 EAGAIN, 读不到请求数据

程序代码:
#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <netinet/in.h>
#include <arpa/inet.h>

#include <sys/types.h>
#include <sys/socket.h>

#include <sys/epoll.h>

#include <errno.h>

#define MAX_EVENTS 1000

#define HTTP_RES_BUF "HTTP/1.1 200 OK\r\n" \
    "Content-Type: text/html; charset=utf-8\r\n" \
    "Server: epoll_test\r\n" \
    "Connection: Close\r\n" \
    "Content-Length: 5\r\n" \
    "\r\n" \
    "hello"


int main(void)
{
    int i;
    int ret;
    int listenfd;
    int acceptfd;

    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    socklen_t address_len;

    char recv_buf[8192];
    ssize_t recv_ret;
    int opt = 1;

    int epfd;
    struct epoll_event listen_ent;
    struct epoll_event ep_ent[MAX_EVENTS];

    /* create a tcp socket */
    listenfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
    if (listenfd == -1) {
        perror("socket failed");
        return -1;
    }

    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    epfd = epoll_create(MAX_EVENTS);
    if (epfd == -1) {
        perror("epoll_create failed");
        return -1;
    }
    memset(&listen_ent, 0x00, sizeof(listen_ent));
    listen_ent.data.fd = listenfd;   

    listen_ent.events = EPOLLIN;
    ret = epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &listen_ent);
    if (ret == -1) {
        perror("epoll_ctl failed");
        return -1;
    }

    /* bind */
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8088);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    address_len = sizeof(struct sockaddr);
    ret = bind(listenfd, (struct sockaddr*)&server_addr, address_len);
    if (ret == -1) {
        perror("bind failed");
        return -1;
    }

    /* listen */
    ret = listen(listenfd, MAX_EVENTS);
    if (ret == -1) {
        perror("listen failed");
        return -1;
    }

    printf("=== listen fd(%d)port %d ===\n", listenfd, 8088);

    /* accept new request */
    while (1) {
        ret = epoll_wait(epfd, ep_ent, MAX_EVENTS, -1);
        if (ret == -1) {
            perror("epoll_wait failed");
            return -1;
        }

        for (i = 0; i < ret; i++) {
            printf("active fd = %d\n", ep_ent[i].data.fd);
            if (ep_ent[i].data.fd == listenfd) {
                address_len = sizeof(struct sockaddr);
                acceptfd = accept4(listenfd, (struct sockaddr *)&client_addr, &address_len, SOCK_NONBLOCK);
                if (-1 == acceptfd) {
                    perror("accept4 failed");
                    return -1;
                }

                listen_ent.data.fd = acceptfd;     

                listen_ent.events = EPOLLIN | EPOLLET;
                ret = epoll_ctl(epfd, EPOLL_CTL_ADD, acceptfd, &listen_ent);
                if (ret == -1) {
                    perror("epoll_ctl failed");
                    return -1;
                }
            }
            else {
                if (ep_ent[i].events | EPOLLIN) {   

                    recv_ret = recv(ep_ent[i].data.fd, recv_buf, sizeof(recv_buf), 0);
                    if ((ssize_t)-1 == recv_ret) {
                        if (EAGAIN == errno) {
                            printf("recv EAGAIN\n");
                            continue;
                        }
                        perror("recv failed");
                        return -1;
                    }
                    else if (0 == recv_ret) {
                        printf("client close connection\n");
                    }
                   

                    listen_ent.data.fd = ep_ent[i].data.fd;     

                    listen_ent.events = EPOLLOUT;
                    ret = epoll_ctl(epfd, EPOLL_CTL_MOD, ep_ent[i].data.fd, &listen_ent);
                }
                else if (ep_ent[i].events | EPOLLOUT) {
                    recv_ret = send(ep_ent[i].data.fd, HTTP_RES_BUF, sizeof(HTTP_RES_BUF)-1, 0);
                    if ((ssize_t)-1 == recv_ret) {
                        if (EAGAIN == errno) {
                            printf("send EAGAIN\n");
                            continue;
                        }
                        perror("send failed");
                        return -1;
                    }
                    ret = epoll_ctl(epfd, EPOLL_CTL_DEL, ep_ent[i].data.fd, &listen_ent);
                    close(ep_ent[i].data.fd);
                }
            }
        }
    }

    close(epfd);
    close(listenfd);

    return 0;
}


搜索更多相关主题的帖子: include ret failed return data 
2018-10-18 15:29
烟雨晨曦
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:7
帖 子:150
专家分:599
注 册:2017-3-5
得分:20 
这个改一下
ep_ent[i].events | EPOLLIN  -> ep_ent[i].events & EPOLLIN
2018-10-18 16:58
星泪成寒
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:6
帖 子:75
专家分:539
注 册:2013-5-19
得分:0 
楼上说的是个问题, 贴个正确的代码
程序代码:
#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <netinet/in.h>
#include <arpa/inet.h>

#include <sys/types.h>
#include <sys/socket.h>

#include <sys/epoll.h>

#include <errno.h>

#define MAX_EVENTS 1000

#define HTTP_RES_BUF "HTTP/1.1 200 OK\r\n" \
    "Content-Type: text/html; charset=utf-8\r\n" \
    "Server: epoll_test\r\n" \
    "Connection: Close\r\n" \
    "Content-Length: 5\r\n" \
    "\r\n" \
    "hello"


int main(void)
{
    int i;
    int ret;
    int listenfd;
    int acceptfd;

    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    socklen_t address_len;

    char recv_buf[8192];
    ssize_t recv_ret;
    int opt = 1;

    int epfd;
    struct epoll_event listen_ent;
    struct epoll_event ep_ent[MAX_EVENTS];

    /* create a tcp socket */
    listenfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
    if (listenfd == -1) {
        perror("socket failed");
        return -1;
    }

    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    epfd = epoll_create(MAX_EVENTS);
    if (epfd == -1) {
        perror("epoll_create failed");
        return -1;
    }
    memset(&listen_ent, 0x00, sizeof(listen_ent));
    listen_ent.data.fd = listenfd;   

    listen_ent.events = EPOLLIN | EPOLLET;;
    ret = epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &listen_ent);
    if (ret == -1) {
        perror("epoll_ctl failed");
        return -1;
    }

    /* bind */
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8088);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    address_len = sizeof(struct sockaddr);
    ret = bind(listenfd, (struct sockaddr*)&server_addr, address_len);
    if (ret == -1) {
        perror("bind failed");
        return -1;
    }

    /* listen */
    ret = listen(listenfd, MAX_EVENTS);
    if (ret == -1) {
        perror("listen failed");
        return -1;
    }

    printf("=== listen fd(%d)port %d ===\n", listenfd, 8088);

    /* accept new request */
    while (1) {
        ret = epoll_wait(epfd, ep_ent, MAX_EVENTS, -1);
        if (ret == -1) {
            perror("epoll_wait failed");
            return -1;
        }

        for (i = 0; i < ret; i++) {
            if (ep_ent[i].data.fd == listenfd) {
                while (1) {
                    address_len = sizeof(struct sockaddr);
                    acceptfd = accept4(listenfd, (struct sockaddr *)&client_addr, &address_len, SOCK_NONBLOCK);
                    if (-1 == acceptfd) {
                        if ((EAGAIN == errno) || (EWOULDBLOCK == errno)) {
//                            printf("accept4 EAGAIN\n");
                            break;
                        }
                        perror("accept4 failed");
                        return -1;
                    }

                    listen_ent.data.fd = acceptfd;     

                    listen_ent.events = EPOLLIN | EPOLLET;
                    ret = epoll_ctl(epfd, EPOLL_CTL_ADD, acceptfd, &listen_ent);
                    if (ret == -1) {
                        perror("epoll_ctl failed");
                        return -1;
                    }
                }
            }
            else {
                if (ep_ent[i].events & EPOLLIN) {   

                    recv_ret = recv(ep_ent[i].data.fd, recv_buf, sizeof(recv_buf), 0);
//                    printf("recv %zd\n", recv_ret);
                    if ((ssize_t)-1 == recv_ret) {
                        if (EAGAIN != errno) {
                            perror("recv failed");
                            return -1;
                        }
                    }
                    else if (0 == recv_ret) {
                        ret = epoll_ctl(epfd, EPOLL_CTL_DEL, ep_ent[i].data.fd, &listen_ent);
                        printf("client close connection\n");
                    }
                   

                    send(ep_ent[i].data.fd, HTTP_RES_BUF, sizeof(HTTP_RES_BUF)-1, 0);
                    close(ep_ent[i].data.fd);
                }
            }
        }
    }

    close(epfd);
    close(listenfd);

    return 0;
}



2018-10-19 10:04



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-490486-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.494245 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved