3

TCPソケットを使用するC/Linuxのチャットサーバーがあります。libevを使用すると、ソケットの読み取りイベント用のev_ioウォッチャーを1回作成できます。何かのようなもの:

ev_io* new_watcher = (ev_io*)malloc(sizeof(ev_io));

//initialize the watcher
ev_init(new_watcher, read_cb);

//set the fd and event to fire on write
ev_io_set(new_watcher, watcher->fd, EV_READ);

//start watching
ev_io_start(loop, new_watcher);

読み取りイベントは、読み取るデータがある場合にのみ発生するため、これは正常に機能します。ただし、書き込むデータがない場合でも常に発生するため、書き込みイベントの処理方法を変える必要があります。この問題を解決するために、read_callbackに、書き込みの準備ができているデータがある場合にのみ書き込みデータのev_ioウォッチャーを作成させます。その後、write_callbackは、メッセージを送信した後にウォッチャーを削除します。

これは、メッセージを処理する必要があるたびに、書き込みウォッチャーの割り当て、初期化、設定、監視、監視解除、および割り当て解除を行っていることを意味します。私はこれを誤って非効率的に扱っているのではないかと心配しています。

libevでwrite_callbackイベントを処理するための最良の方法は何ですか?

前もって感謝します。

4

3 に答える 3

5

簡単です。ev_io_stopもあるので、何か書き込むものがない限り、書き込みウォッチャーを起動しません。コールバック内で、バッファー全体を書き込んだときにev_io_stopを呼び出します。

書き込みバッファをオーバーフローすることがめったにない一般的なケースでは(データが小さく、頻繁に書き込みを行わないため)、データを直接(ウォッチャーがアクティブでない場合)書き込みを試みることで、これをより効率的にすることができます。データをバッファリングし、完全に書き込めなかった場合は書き込みウォッチャーを起動します。

上記の仮定の下では、これは、書き込みウォッチャーを起動する必要がほとんどないことを意味します。欠点は非常に複雑なコードであるため、多くの場合、単純な「データを書き込みバッファーに追加し、ウォッチャーを起動し、ウォッチャー内でバッファーが完全に書き込まれた場合は停止する」ロジックから始めるのが最善です。

于 2012-12-22T03:38:14.843 に答える
1

この状況を解決する方法は、バッファーと長さへのポインターを受け取るデータを書き込むための関数を用意することでした。ポインタと長さをキューのデータ構造に格納し、書き込みイベントを有効にします。

書き込みイベントコールバックが発生すると、書き込みキューをチェックして、保留中の書き込みがあるかどうかを確認します。存在する場合は、キュー内の次の保留中の書き込みを取得して、ファイル記述子に書き込みます。次に、書き込みコールバックが終了する直前に、保留中の書き込みキューが空かどうかを確認します。その場合、書き込みイベントを無効にします。

読み取り/書き込みイベントオブジェクトをグローバル変数にすると、それらは一度だけ割り当てられ、解放されます。書き込むデータがあることがわかっている場合は常に書き込みイベントを有効にし、書き込むデータがなくなったら無効にします。

私のコードは上記の説明よりも少し複雑ですが、ご覧いただけるようにここにリンクを投稿します。私が具体的に話しているコードは、aiofd.hとaiofd.c(aiofd==非同期I/ Oファイル記述子)にあります: https ://bitbucket.org/wookie/cutil/

これがお役に立てば幸いです。

于 2012-07-10T20:00:26.357 に答える
1

割り当てによってオーバーヘッドが増える可能性があります。mallocの代わりに静的変数を使用するか、mallocを1回だけ使用して、イベントループが終了した後にのみ解放することができます。書き込みの前に設定し、成功した後に設定を解除するだけです。しかし、はい、それはそれが行われる必要がある方法です。

于 2012-02-29T18:28:44.640 に答える