2

Iamはlibevに基づいたソケットプログラムを作成しようとしています。https://github.com/coolaj86/libev-examples/blob/master/src/unix-echo-server.cに記載されているいくつかの例では、initに基づくコールバックを使用していることに気付きました。例えば、

main() {

......
ev_io_init(&client.io, client_cb, client.fd, EV_READ|EV_WRITE);
ev_io_start(EV_A_ &server.io);

}

static void client_cb (EV_P_ ev_io *w, int revents)
{
  if (revents & EV_READ)
  {
      ....
  } else if (revents & EV_WRITE) {

     ......
  }
}

私の質問は、予想される動作から来ています。たとえば、EV_READで読んだものはすべて、リンクリストに保存されています。読み取るパケットのフリーフローを取得し続けているとしましょう。EV_WRITEに入る機会はありますか?読んだものをすべて別のソケットに送信する必要があります。では、1回はEV_READで、2回目はEV_WRITEになるのでしょうか。言い換えれば、EV_WRITEはいつブロック解除されますか?または、EV_WRITEが呼び出されるようにEV_READをブロックする必要がありますか?誰かが私がこれを理解するのを手伝ってもらえますか?

4

2 に答える 2

2

簡単に答えるには:常に最初に1つのタイプのイベントをチェックしてelse ifから、他のタイプのイベントをチェックすると、飢餓のリスクがあります。一般に、指定されたプロトコルによって両方を同時にアクティブ化することが不可能でない限り、両方をチェックします。

よりわかりやすい答えは次のとおりです。質問のリンクに、質問などのコード構造が含まれていません。クライアントhttps://github.com/coolaj86/libev-examples/blob/master/src/unix-echo-client.cにも同様のコールバックがあります。一度書き込みを行うと、書き込みイベントが無効になります。

// once the data is sent, stop notifications that
// data can be sent until there is actually more
// data to send
ev_io_stop(EV_A_ &send_w);
ev_io_set(&send_w, remote_fd, EV_READ);
ev_io_start(EV_A_ &send_w);

これは、パイプREADイベントブランチの枯渇を回避する試みのように見えます。私はlibevにあまり精通していませんが、リンクしたgithubの例はあまり堅牢ではないようです。たとえば、の戻り値を使用してEOFを検出するstatic void stdin_cb (EV_P_ ev_io *w, int revents)ことはありません。getline()また、send()ソケットrecv()操作の戻り値は、読み取られた量または書き込まれた量については検査されません(ただし、ローカルの名前付きパイプストリームでは、量は要求された量と一致する可能性があります)。これが後でTCPベースの接続に変更された場合は、金額を確認することが重要になります。

于 2013-02-25T09:34:50.123 に答える
2

書き込みコールバックを読み取りコールバックから分離しておく必要があると思います。

main() {
    ev_io_init(&read.io, read_cb, client.fd, EV_READ);
    ev_io_init(&write.io, writead_cb, client.fd, EV_WRITE);
    ev_io_start(EV_A_ &read.io);
    ev_io_start(EV_A_ &write.io);
}

これが私の解決策です。

于 2016-01-21T02:17:32.710 に答える