epoll non-blocking io model, edge trigger I set.
Now the client is a browser. The form uploads a 2M file. The server monitors the readable event. I use recv to obtain it. Why is the data received incomplete and returns -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 is large enough. Could it be that the send speed is slower than the recv speed, causing the tcp receiving buffer to be empty? Does the recv return without blocking? How to deal with it?
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;
}
}
}
Because the follow-up data has not arrived yet. You continue to wait for the epoll notification.