2009-06-15 7 views
1

ほとんどの場合、すべてのデータが送信された状態でsend()が成功しますが、常にそうであるとは限りません。したがって、select()とpoll()のためにwrite-fdsetを使用して、ソケットが書き込み可能かどうかを調べることをお勧めします。send()とselect()のデータをバッファリングする方法は?

よく理解できるソースコードを維持しながら、送信するデータを実際にバッファリングするような通常のメカニズムはどのように見えますか?

+0

これ以上のC++の質問はありませんか?それを取り戻すことができます。 –

答えて

1

我々はC++の土地にいるとして、あなたはSTDにデータを格納することができ::ベクトル

新しいデータがベクトルの最後に追加されます。ソケットが書き込み可能であるという通知を受け取ったら、完全なベクターを送信してみてください。 send()はどれくらい実際に送られたかを返します。その後、単純にベクトルの先頭からそのバイト数を消去:

std::vector<char> buffer; 
... 
if(! buffer.empty()) 
{ 
    int bytesRead = send(socket, &buffer[ 0 ], buffer.size(), flags); 
    if(bytesRead > 0) 
     buffer.erase(0, bytesRead); 
    else 
     // some error... 
} 

はそうすることを確認する多くのエラーはおそらくありますが、あなたのアイデアを得ますか?

個々の送信要求をキューに入れるのではなく、TCPを使用していると仮定して複数の上位レベルの送信を1つのソケット送信に組み合わせることができます。

Remusには、あなたのフロー制御とAPIが厄介な点が書かれています。つまり、どのようにバッファーが大きくなり過ぎるのを止めますか?

+0

これは良い例ですが、私の最初の愚痴は、あなたが頭を消すときに不要なベクトルの尾をコピーすることです - 私はここで円形バッファのいくつかの並べ替えを使用したい、2番目のニックピットは、そのサイズが変更されると、手動で行う必要があります。 –

1

私はソケットプログラミングの* nix側に深く慣れていませんが、Win32側で同じ問題が発生しました。バッファリングはそれほど問題ではありません(要求をキューに入れ、キューから次に送信するために書き込み完了を覗く)。実際の問題は、実際にフロー制御を処理しており、フロー制御を解決できないという信号をバッファリングする必要があるということですバッファリングだけでは、プロデューサよりも消費者の方が遅くなり、バッファは基本的に制御不能になります。データを生成しているどのモジュールにでもストリームの上にフロー制御を伝播させる必要があり、これは本当に複雑なインターフェースを作ります。すべての '書込み'要求は、フロー制御状態を示すリターンコード(つまり、「書込みの停止」、「スペースがない」)およびコールバックによる書込み操作の再開をサポートする必要があります。

1

select()/ poll()ループを中心にする必要があるOOを書くときには、適切な抽象化が必要です。私はいつもAdaptive Communications Environment(ACE)Reactorクラスがこの点で非常に優れていることを発見しました。この環境をカバーするDoug Schmidtの書籍「C++ Network Programming」もあります。The Design and Use of the ACE Reactor

関連する問題