web-dev-qa-db-ja.com

CおよびLinuxのソケットで使用可能なデータ量を確認する方法

データの連続ストリームを受信するサーバーがあります。ソケットから複数回読み取るのではなく、read()への1回のシステムコールでソケット受信バッファーのデータ全体を読み取りたいと思います。

もちろん、大きなバッファを渡すことができ、read()は利用可能なすべてのデータでそれを埋めようとします。しかし、ほとんどの場合、mallocされたバッファはソケットで利用可能な実際のデータよりも大きいため、これは多くのメモリを無駄にします。ソケットで使用可能なデータを照会する方法はありますか?

30
Jimm

はい:

#include <sys/ioctl.h>

...

int count;
ioctl(fd, FIONREAD, &count);
52
fizzer

いいえ、ありません。これを行う方法があったとしても、新しいデータはいつでも到着する可能性があるため、得られる回答はすぐに古くなってしまいます。

read()にバッファを渡すと、バッファが待機するのではなく、any読み取るデータ量(少なくとも1バイト)があると、関数が返されることに注意してください。完全に埋めます。

4
Greg Hewgill

これは「一種の」答えです: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の背後にある理由です

2
jim mcnamara

コマンドの送受信を試行する必要があります。また、文字を1つずつソケットで読み書きできるので、メモリを無駄にせず、コミュニケーションを向上させることができます。

2
ravi bhuva

非ブロッキングソケット 、またはselect()/ poll()を使用できます。新しいデータを待っている間に他のことを行うことができるので、非ブロッキングソケットを好みます。

1
yeyo

システムコールによるオーバーヘッドを減らすために、単一のシステムコールで多くのパケットを取得しようとしていると思います。

Linux 2.4または2.6+カーネル用のパケットソケットインターフェイスこれを試してください http://lxr.free-electrons.com/source/Documentation/networking/packet_mmap。 txt

0
akp