epoll + 非阻塞io模型 , 我设置的边沿触发.
现在客户端是浏览器,form表单上传一个2M文件, 服务端监听到可读事件, 我用recv获取, 为什么数据会接受不完全,返回-1, errno = EAGAIN.
while(len > 0){
recvbytes = recv(client_fd, cur_recv, MAX_RECV_SIZE, 0);
if(-1 == recvbytes && errno == EAGAIN){
err_sys("recv http body fail", DEBUGPARAMS);
return -1;
}
cur_recv += recvbytes;
len -= recvbytes;
}
cur_recv足够大, 难道是send速度比recv速度慢, 导致tcp接收缓冲区为空, recv不阻塞返回了吗, 该怎么处理呢?
while(1){
ret = epoll_wait(epfd, events, MAX_FD, -1);
/* 遍历 */
for(i = 0; i < ret; i++){
http_request *hr = (http_request *)events[i].data.ptr;
/* 检测套接字是否存在连接*/
if(sockfd == hr->sockfd){
int client_fd;
while(1){
if(-1 == (client_fd = accept(sockfd, (struct sockaddr *) &client_sock, &sin_size))){
if((errno == EAGAIN) || (errno == EWOULDBLOCK)){
break;
}else{
err_sys("accept() fail", DEBUGPARAMS);
break;
}
}
set_non_blocking(client_fd);
http_request *request = (http_request *)malloc(sizeof(http_request));
init_http_request(request, client_fd, epfd);
event.data.ptr = (void *)request;
event.events = EPOLLIN | EPOLLET | EPOLLONESHOT; //可读 + 边沿触发 + 避免分配给多个线程
if(-1 == (ret = epoll_ctl(epfd, EPOLL_CTL_ADD, client_fd, &event))){
err_sys("epoll_ctl fail", DEBUGPARAMS);
break;
}
}
}else{
if((events[i].events & EPOLLERR) || events[i].events & EPOLLHUP || (!(events[i].events & EPOLLIN))){
close(hr->sockfd);
continue;
}
/*添加到线程池工作队列*/
if(-1 == add_job(handle_request, events[i].data.ptr)) break;
}
}
}
回答
因为后续数据还没到。你继续等 epoll 通知呗。