epoll + modèle io non bloquant, déclencheur de bord que j'ai défini.
Maintenant, le client est un navigateur et le formulaire télécharge un fichier 2M. Le serveur surveille l'événement lisible. J'utilise recv pour l'obtenir. Pourquoi les données reçues sont-elles incomplètes et renvoient -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 est suffisamment grand. Se pourrait-il que la vitesse d'envoi soit plus lente que la vitesse de réception, ce qui rendrait le tampon de réception TCP vide ?
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 通知呗。