2011-06-23 108 views
0
while(m_severRun){ 

    printf("ServerManager::eventAcceptLoop, epoll_wait\n"); 
    int event_cnt = epoll_wait(m_epfd, m_events, EPOLL_SIZE, -1); 
    if(event_cnt == -1){ 
     perror("epoll_wait error \n"); 
     break; 
    } 

    for(int i=0; i<event_cnt; i++){ 

     SocketClient *conn = reinterpret_cast<SocketClient *>(m_events[i].data.ptr); 


     if(conn->getFd() == m_serverSocket->getFd()){ 

      printf("ServerManager::eventAcceptLoop, A Client has been connected \n"); 

      struct sockaddr_in clnt_adr; 
      socklen_t adr_sz = sizeof(clnt_adr); 
      int clnt_sock = accept(m_serverSocket->getFd(), (struct sockaddr*)&clnt_adr, &adr_sz); 

      SocketClient* client = new SocketClient(clnt_sock); 
      if(!addClient(client)) 
       break; 
     } 
     else{ 

      if(m_events[i].events & EPOLLRDHUP){ 
       printf("ServerManager::eventAcceptLoop, EPOLLRDHUP \n"); 
       removeClient(conn); 
       close(conn->getFd()); 
       continue; 
      } 

      if(m_events[i].events & EPOLLIN){ 

       printf("ServerManager::eventAcceptLoop, EPOLLIN \n"); 
       int recv = conn->recv(); 

       if(recv <= 0){ 
        removeClient(conn); 
        close(conn->getFd()); 
       } 
       else{ 
        printf("ServerManager::eventAcceptLoop, A message has been received \n"); 
        vector<char> data = conn->getData(); 
        addWork(conn, data); 
       } 
      } 

      if(m_events[i].events & EPOLLERR) 
       printf("ServerManager::eventAcceptLoop, EPOLLERR \n"); 
     } 
    }//for loop end 
}//while loop end 

我工作的一個網絡編程(TCP)和我有這樣的代碼。這是我第一次使用epoll,所以我不確定這個設計是否正確。另外,我使用一個線程池(5子線程),每當我讀epoll的數據我把那線程池中的隊列中。問題是,在閱讀功能,我可以看到瓶頸問題。epoll的架構問題,瓶頸問題

在讀出功能,它調用ObserveSocket

int SocketClient::ObserveSock(int sock, int timeout){ 

    printf("SocketClient::ObserveSock called\n"); 

    fd_set reads; 
    int fd_max; 
    struct timeval _timeout; 

    FD_ZERO(&reads); 
    FD_SET(sock, &reads); 
    fd_max = sock + 1; 

    _timeout.tv_sec = timeout; 
    _timeout.tv_usec = 0; 

    return select(fd_max, &reads, 0, 0, &_timeout); 
} 

它手錶插座,並且如果存在一定量的時間內沒有信號,則它返回0關閉套接字。我想我需要這個代碼來檢測意外的用戶斷開連接或數據損壞(客戶端發送100個字節,但是服務器接收到的90個字節,則服務器會等待不會到達最後10個字節)。

我會很感激,如果你們能告訴我怎樣才能解決這個瓶頸問題,並在此架構的任何問題。

我也將尋找任何好的教程,使用epoll的,涵蓋異常處理的細節。

在此先感謝。

編輯

內的recv()函數,它只是調用讀取功能之前,我讀我所說的ObserveSocket

+0

「在讀取函數中,它調用ObserveSocket」 - 什麼是「讀取」函數?你的意思是SocketClient :: recv()?你有太多的電話在這裏,你既沒有提供也沒有描述的功能...... – Nemo

回答

2

這手錶的插座,如果有 一定金額的無信號時間 然後返回0關閉套接字。

爲什麼?

我想我需要這個代碼detectever 意想不到的用戶斷開連接或數據損壞 (客戶端發送100個字節,但 服務器接收到的90個字節,則 服務器將等待最後10個字節 ,不會到達)。

你不知道。您將獲得另一個讀取事件,其中讀取將返回0,指示EOS或錯誤事件。

如果你想實現一個不活動超時,你必須實現它的主要選擇循環。也就是說,要記住每個套接字的最後一次活動時間,如果它太長,關閉套接字或做任何你必須做的事情。在迭代並再次調用select()之前,將此測試放在select()循環的底部。

目前每次讀取事件被阻斷超時時間所有其他選擇()事件。所以你的整個服務器被阻止。

+0

所以你說,如果客戶端發送100字節,但服務器以某種方式接收90字節(數據損壞或什麼),然後epoll通過閱讀零?所以我不必擔心這個問題?這是你的意思嗎?預先感謝... – codereviewanskquestions

+0

@LCYSoft在我長期的論壇經歷中讓我告訴你,每當有人問'所以你說...'的答案總是'不'。正如在這種情況下。我沒有說這些;我並沒有暗示任何這一點;我沒有打算這麼做。如果您只接收100個字節中的90個字節,則其他十個字節必須仍處於傳送狀態。正確的解決方案不是用你自己的個人select()在這個特定的套接字上阻塞世界,而是返回到select()循環並讓它處理所有傳入的事件,包括這個套接字上的下一個數據。並相應地調整你的代碼。 – EJP

+0

感謝您的回答..如果客戶端因爲某種原因發送90字節後斷開連接會怎麼樣? – codereviewanskquestions