有大佬懂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; }