首頁  >  問答  >  主體

linux - epoll + 非阻塞IO接收資料問題

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;
            }
        }
    }
PHP中文网PHP中文网2701 天前750

全部回覆(1)我來回復

  • 滿天的星座

    滿天的星座2017-05-27 17:46:36

    因為後續數據還沒到。你繼續等 epoll 通知唄。

    回覆
    0
  • 取消回覆