2011-06-23 24 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アーキテクチャの問題

、それはソケットを監視し、一定時間信号がない場合、それは、ソケットを閉じるために0を返す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); 
} 

を呼び出します。私は予期せぬユーザーの切断やデータの破損を検出するためにこのコードが必要だと思っています(クライアントは100バイトを送信しましたが、サーバーは90バイトを受信した後、サーバーは到着しない最後の10バイトを待ちます)。

ボトルネックの問題とこれに関するアーキテクチャ上の問題をどのように修正できるか教えていただければ幸いです。

また、epollを使用し、例外処理について詳しく説明した良いチュートリアルを探します。

ありがとうございます。

のrecvの内部EDIT

は()それだけで読んで関数を呼び出すと、私は読む前に、私はObserveSocketを呼び出す機能

+0

"読み取り機能ではObserveSocketを呼び出します" - どのような "読み取り"機能ですか?あなたはSocketClient :: recv()を意味しますか?あなたが提供していない関数にはあまりにも多くの呼び出しがあります... – Nemo

答えて

2

それはソケットを監視し、一定量のための信号 が存在しない場合時刻 それから0を返してソケットを閉じます。

なぜですか?私は、クライアントが100のバイトを送ったが、 サーバは、その後 サーバが到着しないだろう、最後の10バイト を待ちます90のバイトを受信( 予期しないユーザーの切断やデータ 破損をdetecteverするために、このコードが必要と思った

)。

あなたはありません。 readでEOSを示す0またはエラーイベントが返される別のreadイベントが発生します。

非アクティブタイムアウトを実装する場合は、メインの選択ループにを実装する必要があります。つまり、各ソケットの最後の活動時間を記録しておき、それが長すぎるとソケットを閉じるか、何をしなくてもかまいません。 select()を繰り返し実行する前に、このテストをselect()ループの一番下に置いてください。

現在、すべての読み取りイベントは、タイムアウト期間中、他のすべてのselect()イベントをブロックしています。したがって、サーバー全体がブロックされます。

+0

クライアントは100バイトを送ったが、何とか90バイトしか受信しなかった場合(データの破損など)、epollはこの問題の原因を読み取りゼロ?私はこの問題について心配する必要はありませんか?あなたの言っていることですか?少し早いですがお礼を... – codereviewanskquestions

+0

@LCYSoftは私の長年のフォーラムの経験の中で、誰かが「あなたが言っているように...」と尋ねると必ず答えが返されます。この場合のように。私はそのことを言わなかった。私はそれを暗示しませんでした。私はそれを意図していませんでした。 100のうち90バイトしか受信しない場合は、残りの10バイトはまだ転送中でなければなりません。この正しい解決策は、この特定のソケットで自分のselect()を使って世界をブロックするのではなく、select()ループに戻り、このソケットの次のデータを含む*すべての着信イベントを処理させることです。それに応じてコードを調整します。 – EJP

+0

あなたの答えをありがとう。何らかの理由でのみ90バイトを送信した後でクライアントが切断された場合はどうなりますか? – codereviewanskquestions

関連する問題