36

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

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

4

6 に答える 6

63

はい:

#include <sys/ioctl.h>

...

int count;
ioctl(fd, FIONREAD, &count);
于 2012-12-27T21:55:01.330 に答える
5

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

にバッファを渡すと、バッファが完全にいっぱいになるのを待つのではなく、読み取るデータの量(少なくとも1バイト)read()があるときに関数が戻ることに注意してください。

于 2012-12-27T00:06:38.897 に答える
3

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

于 2012-12-27T01:34:08.803 に答える
2

これは「一種の」答えです。recv(char* buffer, size_t nytes, int 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

于 2012-12-27T02:08:22.513 に答える
1

送受信コマンドを試す必要があります。また、文字ごとにソケットの読み取りと書き込みができるため、メモリの浪費がなく、通信がさらに向上します。

于 2012-12-27T16:11:34.943 に答える
0

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

したがって、Linux 2.4または2.6以降のカーネル用のPACKETソケットインターフェイスを試すことができます。http://lxr.free-electrons.com/source/Documentation/networking/packet_mmap.txtを試してください。

于 2012-12-27T09:44:06.377 に答える