web-dev-qa-db-ja.com

C ++で 'MSG_PEEK'を使用して 'recv'によってソケットで使用可能なバイト数を取得する

C++には、ソケットからバイトを受信する次の関数があり、MSG_PEEKフラグで使用可能なバイト数を確認できます。 MSG_PEEKの場合、 'recv'の戻り値は、ソケットで使用可能なバイト数です。

#include <sys/socket.h>
ssize_t recv(int socket, void *buffer, size_t length, int flags); 

bufferを作成せずに(bufferにメモリを割り当てずに)ソケットで使用可能なバイト数を取得する必要があります。それは可能ですか?

13
jondinham

あなたが探しているのはioctl(fd,FIONREAD,&bytes_available)で、ウィンドウの下はioctlsocket(socket,FIONREAD,&bytes_available)です。

ただし、OSはバッファリングするデータ量を必ずしも保証するわけではないため、非常に多くのデータを待っている場合は、データを読み込んで独自のバッファに格納する方がよいでしょう。何かを処理するために必要なものがすべて揃うまで。

これを行うには、通常、次のように一度にチャンクを読み取るだけです。

char buf[4096];
ssize_t bytes_read;
do {
     bytes_read = recv(socket, buf, sizeof(buf), 0);
     if (bytes_read > 0) {
         /* do something with buf, such as append it to a larger buffer or
          * process it */
     }
} while (bytes_read > 0);

また、データを待機したくない場合は、selectまたはepollを調べて、データを読み取る準備ができているかどうかを判断し、O_NONBLOCKソケットのフラグは、recvでブロックしないようにする場合に非常に便利です。

33
hexist

Windowsでは、 ioctlsocket() 関数をFIONREADフラグと一緒に使用して、実際のバイト自体を読み取ったり調べたりする必要なく、使用可能なバイト数をソケットに要求できます。 。返される値は、recv()がブロックせずに返すことができる最小バイト数です。実際にrecv()を呼び出すときには、さらに多くのバイトが到着している可能性があります。

3
Remy Lebeau