2009-06-25 18 views
0

私は単純なソケットラッパークラスを実装しました。これは、非ブロック機能が含まれています。クラスは、単純な関数受け取る含まノンブロッキングUnixソケットの高速化(C++)

void Socket::set_non_blocking(const bool b) { 
    mNonBlocking = b; // class member for reference elsewhere 
    int opts = fcntl(m_sock, F_GETFL); 
    if(opts < 0) return; 
    if(b) 
     opts |= O_NONBLOCK; 
    else 
     opts &= ~O_NONBLOCK; 

    fcntl(m_sock, F_SETFL, opts); 
} 

:実際には

int Socket::recv(std::string& s) const { 
    char buffer[MAXRECV + 1]; 
    s = ""; 
    memset(buffer,0,MAXRECV+1); 
    int status = ::recv(m_sock, buffer, MAXRECV,0); 

    if(status == -1) { 
    if(!mNonBlocking) 
     std::cout << "Socket, error receiving data\n"; 

     return 0; 
    } else if (status == 0) { 
     return 0; 
    } else { 
     s = buffer; 
     return status; 
    } 
} 

を、〜15msの遅延時にソケット::のrecv(があるように思われます)と呼ばれる。この遅延は避けられますか? select()を使用する非ブロッキングの例をいくつか見てきましたが、どのように役立つか理解できません。

答えて

1

どのようにソケットを使用しているかによって異なります。複数のソケットがあり、それらのすべてをループして、遅延を考慮している可能性のあるデータをチェックします。

ノンブロッキングrecvでは、そこにあるデータによって異なります。アプリケーションで複数のソケットを使用する必要がある場合は、各ソケットを順番にプールして、いずれかのソケットにデータがあるかどうかを調べる必要があります。

これはシステムリソースには悪いことです。これは、何もしなくてもアプリケーションが常に実行されていることを意味します。

これを避けるには、selectを使用します。あなたは基本的にあなたのソケットを設定し、それをグループに追加してグループ上で選択します。選択したソケットのいずれかで何かが発生した場合、selectは何が起こったのか、どのソケットにあるのかを返します。 beej's guide to network programming

+0

アドバイスありがとうございますが、私の問題は文字通りrecv()への呼び出しが受け入れがたい15ミリ秒の遅延を表示しているソケットを1つしか考えていません。それは1つのソケットをポーリングするだけなので、私は問題を推測するには間違っていますか? – duckworthd

+0

他の要因があるかもしれません、起こっているコードの少量に基づいて伝えることができません。ソケットが1つだけで、データを待っていると仮定します。なぜ非ブロック化を使用しますか?データを待っている間に何か他のことをしているということですか?他の作品が到着するとすぐにデータを受け取ることができますか? – stefanB

+0

@duckworthdあなたはrecv()のまわりであなたのタイマーを正確にスタート/ストップさせますか?また、実際にはエラーチェックを行っていません。 -1はあなたが想定するEAGAIN以外のものかもしれません。期待しているデータを入手していますか? – Duck

0

で選択を見て使用する方法についていくつかのコードの場合

はあなたのタイムアウトを指定できるようになる、とソケットから読み込み可能な状態かどうかをテストすることができますを選択します。したがって、15msよりも小さいものを使用することができます。ちなみに、あなたが持っているコードに注意する必要があります。ワイヤ上のデータに埋め込みNULが含まれていて、すべての読み込みデータが含まれていない場合です。 s.assign(buffer, status);のようなものを使用してください。

0

stefanBに加えて、毎回あなたのバッファをゼロにしていることがわかります。なぜ迷惑? recvは、実際に読み取られたバイト数を返します。 1バイト後にゼロをゼロにする(バッファ[status + 1] = NULL)

+0

ほぼすべての実装で効果的ですが、NULL定数(ポインタ用)が文字 '\ 0'と常に同じであることが保証されているかどうかはわかりません。 –

0

MAXRECVの値はどれくらいですか?スタックの成長にページフォールトが発生することがあります。受信バッファをゼロにすることはまったく不要であることに他の人が既に言及しています。受け取った文字データのうちstd::stringを作成すると、メモリ割り当てとコピーヒットが行われます。