データの連続ストリームを受信するサーバーがあります。ソケットから複数回読み取るのではなく、read()
への1回のシステムコールでソケット受信バッファーのデータ全体を読み取りたいと思います。
もちろん、大きなバッファを渡すことができ、read()
は利用可能なすべてのデータでそれを埋めようとします。しかし、ほとんどの場合、mallocされたバッファはソケットで利用可能な実際のデータよりも大きいため、これは多くのメモリを無駄にします。ソケットで使用可能なデータを照会する方法はありますか?
はい:
#include <sys/ioctl.h>
...
int count;
ioctl(fd, FIONREAD, &count);
いいえ、ありません。これを行う方法があったとしても、新しいデータはいつでも到着する可能性があるため、得られる回答はすぐに古くなってしまいます。
read()
にバッファを渡すと、バッファが待機するのではなく、any読み取るデータ量(少なくとも1バイト)があると、関数が返されることに注意してください。完全に埋めます。
これは「一種の」答えです:recv(char* buffer, size_t nytes, int flags)
ここで、flagsは次とORされます:
MSG_PEEK
This flag causes the receive operation to return data from the beginning of the receive queue without removing that data from the queue. Thus, a subsequent receive call will return the same data.
これにより、バッファを不可逆的に読み取ることなく、バッファに任意のバイト数が存在するかどうかを確認できます。これは最も効率的な方法ではないため、半分の回答です。MSG_PEEKは通常、メッセージに次のような既知の長さのヘッダーがある場合に使用されます。
000123DT001
00123
はヘッダーを含むメッセージ全体の長さ、DT
はメッセージのタイプ、001
は送信者による再試行の回数です。アイデアは、何バイトがメッセージを完全に読み取るかを伝える何かをフェッチできるということです。メッセージには興味がありません。しかし、それがMSG_PEEK
の背後にある理由です
コマンドの送受信を試行する必要があります。また、文字を1つずつソケットで読み書きできるので、メモリを無駄にせず、コミュニケーションを向上させることができます。
非ブロッキングソケット 、またはselect()/ poll()を使用できます。新しいデータを待っている間に他のことを行うことができるので、非ブロッキングソケットを好みます。
システムコールによるオーバーヘッドを減らすために、単一のシステムコールで多くのパケットを取得しようとしていると思います。
Linux 2.4または2.6+カーネル用のパケットソケットインターフェイスこれを試してください http://lxr.free-electrons.com/source/Documentation/networking/packet_mmap。 txt