问题描述
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; }} }
问题解答
回答1:因为后续数据还没到。你继续等 epoll 通知呗。