0

Rant: 私はboost::asioが本当に嫌いなので、代替案を探していて、libevに出会いました。これは私には十分に単純に思えますが、理解できないいくつかのことを行っています。1 つのスレッドで質問が多すぎる場合は、お知らせください。

1)リスニングソケットをNON_BLOCKに設定し、受け入れられた各着信接続もNON_BLOCKに設定しましたが、コードのどこかでソケットがBLOCKに変わります。元:

bool Server::Start()
{
    // Setup event loop
    loop = ev_default_loop(EVBACKEND_SELECT); //EVFLAG_AUTO ?
    // Create Socket
    sockfd = socket(PF_INET, SOCK_STREAM, 0);
    addr_len = sizeof(addr)
    // Set Socket to non blocking
    fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK);
    if (fcntl(sockfd, F_GETFL) & O_NONBLOCK) std::cout << "Socket is NONBLOCK" << std::endl;
    else std::cout << "Socket is BLOCK" << std::endl;
    if (sockfd < 0) {
        std::cout << "ERROR opening socket" << std::endl;
        return false;
    }
    bzero((char *)&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;
    // Bind port to socket
    if (bind(sockfd,(struct sockaddr*)&addr, sizeof(addr))!=0) {
        std::cout << "bind error" << std::endl;
        return false;
    }
    // Listen
    if (listen(sockfd, 2) < 0) {
        std::cout << "listen error" << std::endl;
        return false;
    }
    // Initialize and start a watcher to accepts client requests
    ev_io_init(&w_accept, accept_cb, sockfd, EV_READ);
    ev_io_start(loop, &w_accept);
    return true;
}

メインループもブロックしないようにしました:

void Server::MainLoop()
{
    // Start infinite loop
    while (1) {
        ev_loop(loop, EVLOOP_NONBLOCK);
    }
}

しかし、それは違いを生んだようには見えません。ドキュメント (インターネット上で入手できる唯一のドキュメント ソース) にリダイレクトしないでください。私はそれを読みました。

受け入れられたクライアントソケットに対してこれを行います:

void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
....
c->client_sd = accept(watcher->fd, (struct sockaddr *)&c->client_addr, &c->client_len);
....
ev_io *w_client = (struct ev_io*) malloc (sizeof(struct ev_io));
ev_io_init(w_client, read_cb, c->client_sd, EV_READ);
ev_io_start(loop, w_client);
fcntl(watcher->fd, F_SETFL, fcntl(watcher->fd, F_GETFL) | O_NONBLOCK);

それでも、読み取りコールバックが実行されるたびに、ソケットは魔法のように BLOCK に設定されます

2) ソケットのタイムアウトを設定しようとしました: struct timeval timeout;

timeout.tv_sec = 10;
timeout.tv_usec = 0;

if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
            sizeof(timeout)) < 0)
    error("setsockopt failed\n");

if (setsockopt (sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout,
            sizeof(timeout)) < 0)
    error("setsockopt failed\n");

(ここから取得:この質問) それは単に機能しません。これは、ソケットが BLOCKing モードにリセットされたためですか?

3) libev の C++ ラッパーを見たことがあります。コールバックを静的関数にしなければならないという事実は絶対に嫌いです。それは私にとってすべてを台無しにします。それでも、私が見たすべての例は次のように使用されています。

signal.loop.break_loop();

loop.run(0);

おかしなことに、次のものが生成されます。

エラー: 'struct ev::loop_ref' には 'break_loop' という名前のメンバーがありません エラー: 'struct ev::default_loop' には 'run' という名前のメンバーがありません</p>

Debian Squeeze で。

だから、私が求めているのは:

  1. 何、誰、ソケットが NON_BLOCK から BLOCK に変更されたのはどこですか?
  2. ソケットのタイムアウトを設定する方法 (場合) (ブロックまたは非ブロック)
  3. ev++.h の何が問題なのですか? また、なぜ私が使用できないラッパーを使用しているのですか?

ソケットを使用してデータを読み取ったり送信したりできますが、タイムアウトなしでブロックする方法であることに注意してください。さらに、これはサーバーであるため、接続されたクライアントごとにメッセージを保存する必要があるため、コードをクラスに保持する必要があります。この静的メソッドまたは非クラス メソッドを作成すると、単にそれが台無しになるか、非常に異なるアプローチを取らざるを得なくなります。

PS: libev に代わるものはありますか?

4

1 に答える 1

3

クライアント FD を非ブロック モードに設定していません。リスニング ソケット FD を設定しています。

于 2012-12-09T00:56:16.843 に答える