ここでの本当の答えは、 cnicutar が言ったように select(2) を使用することです。トビー、あなたが理解していないのは、競合状態にあるということです。まず、ソケットを見て、そこに何バイトあるか尋ねます。次に、コードが「ここにデータがありません」ブロックを処理している間、アプリケーションとは非同期のハードウェアと OS によってバイトが受信されます。そのため、recv() 関数が呼び出されるまでに、「利用可能なバイトがありません」という答えはもはや真実ではありません...
if ( ioctl (m_Socket,FIONREAD,&bytesAv) < 0 )
{ // Error
}
// BYTES MIGHT BE RECEIVED BY HARDWARE/OS HERE!
if ( bytesAv < 1 ) // AND HERE!
{
// No Data Available
// BUT BYTES MIGHT BE RECEIVED BY HARDWARE/OS HERE!
}
// AND MORE BYTES MIGHT BE RECEIVED BY HARDWARE/OS HERE!
bytesRead = recv(m_Socket,recBuffer,BUFFERLENGTH,flags);
// AND NOW bytesRead IS NOT EQUAL TO 0!
確かに、わずかな睡眠で 2 年前にプログラムが修正された可能性があります。
さらに、Karoly Horvath が言ったように、ユーザーが渡したバッファに格納できる以上のバイトを読み取らないように recv に指示できます。その後、関数インターフェイスは「この fn はソケットで利用可能なバイト数を返しますが、 [渡したバッファ サイズ] 以下です。」
これは、この関数がバッファのクリアについて心配する必要がないことを意味します。呼び出し元は、関数からすべてのバイトをクリアするために必要な回数だけ関数を呼び出すことができます (または、データ ホールセールを破棄し、特定のデータ収集関数でその機能を結び付けない別の fn を提供することもできます)。あまりにも多くのことをしないことで、関数はより柔軟になります。次に、特定のアプリケーションのデータ転送のニーズに適したラッパー関数を作成できます。その fn は、その特定のアプリの必要に応じて get_data fn と clear_socket fn を呼び出します。今、あなたはプロジェクトからプロジェクトへと持ち運ぶことができるライブラリを構築しています。コードを持ち歩ける雇用主がいるほど幸運であれば、仕事から仕事へと持ち運ぶことができるかもしれません。