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



