2012-02-26 5 views
2

私はTCPソケットを使ってC/Linuxにチャットサーバーを持っています。 libevを使用している場合、私はソケットの一度だけreadイベント用のev_ioウォッチャーを作成することができます。以下のような何か:Libev - I/Oコールバック

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イベントを処理する最も良い方法は何ですか?

ありがとうございます。

答えて

0

割り当てに多少のオーバーヘッドが追加される可能性があります。イベントループが終了した後は、mallocではなく静的変数mallocを1回だけ使用できます。 成功すると書き込みおよび設定解除する前に設定する必要があります。しかし、はい、そうする必要があります。

0

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

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

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

私のコードは上記の説明よりも少し複雑ですが、ここではリンクを投稿してみます。私が話しているコードは、特にaiofd.hとaiofd.c(aiofd ==非同期入出力ファイル記述子)です。https://bitbucket.org/wookie/cutil/

これが役立つことを願っています。

4

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

データが小さく、頻繁に読み込まないため、書き込みバッファがオーバーフローすることはほとんどありませんが、データを直接書き込むことで効率を上げることができます(ウォッチャーがデータをバッファリングして完全に書き込めない場合は書き込みウォッチャーを開始するだけです)。

上記の前提の下では、書き込みウォッチャーを開始する必要はほとんどありません。欠点は非常に複雑なコードなので、多くの場合、バッファを書き込むためにデータを追加し、ウォッチャーを起動するだけで、バッファが完全に書き込まれた場合はウォッチャー内で停止させることをお勧めします。