每一天至少有一个观察者失败

libev more then one watcher per fd fails

本文关键字:观察者 失败 有一个 每一天      更新时间:2023-10-16

我似乎不能得到工作2个观察者每个插座。下面的代码实际上根本不起作用,但是如果我混淆了这些调用(例如,为一个观察者调用init/set/start,然后为其他观察者调用),我只得到一个观察者工作。我是不是错过了什么?我不认为这与循环和设置有任何关系……我有1个接受循环(默认循环)和1个循环接受连接。我尝试了这两种方法,在接受连接后直接运行下面的代码,然后通过ev_async_send(…),然后从其他io循环执行此代码。结果是一样的。另外,在一个监视器上设置两个事件也可以。

谢谢

ev_init (pSockWatcher->_wW, &CNetServer::send_cb);
ev_init (pSockWatcher->_wR, &CNetServer::recv_cb);
ev_io_set (pSockWatcher->_wW, pSockWatcher->_sd, EV_WRITE );
ev_io_set (pSockWatcher->_wR, pSockWatcher->_sd, EV_READ );

ev_io_start (loop, pSockWatcher->_wR);
ev_io_start (loop, pSockWatcher->_wW);

嗯,这里有一个在一个套接字fd上有两个I/O监视器的例子,这对我来说似乎工作得很好。我正在使用ev_io_init()函数,但是,不是ev_init()和ev_set()。

#include <ev.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
static struct ev_loop *loop;
static ev_timer timeout_watcher;
static ev_io in_watcher, out_watcher;
static ev_idle idle_watcher;
static int sock_fd;
// socket input watcher
static void in_cb(EV_P_ ev_io *watcher, int revents) {
    int r, t;
    char buf[1024];
    for (t = 0; (r = read(sock_fd, buf, sizeof(buf))) > 0;) {
        t += r;
        write(STDOUT_FILENO, buf, r); // copy input to stdout
        if (buf[r-1] == 'n') break; // operate line-at-a-time
    }
    fprintf(stderr, "in: count = %dn", t);
    if (r == 0) {
        fputs("in: connection closedn", stderr);
        ev_io_stop(loop, &in_watcher); // stop the socket watcher
        ev_break(loop, EVBREAK_ALL); // exit the loop
    } else if (r < 0) {
        perror("read");
    }
}
// socket output watcher
static void out_cb(EV_P_ ev_io *watcher, int revents) {
    int r, t, lim;
    char buf[1024];
    ev_io_stop(loop, &out_watcher);
    for (t = 0; t < sizeof(buf); t++) {
        buf[t] = 'a' + (rand() % 26);
    }
    for (t = 0, lim = rand() % 10000 + 1000;
            (r = write(sock_fd, buf, (lim - t > sizeof(buf)) ? sizeof(buf) : lim - t)) > 0;) {
        t += r;
        if (t >= lim) break;
    }
    if (r < 0) {
        perror("write");
    }
    fprintf(stderr, "out: finished sending, count = %dn", t);
}
static void timeout_cb(EV_P_ ev_timer *watcher, int revents) {
    fprintf(stderr, "timeout: now = %fn", ev_now(loop));
    // send a bunch of stuff on the socket when able
    ev_io_start (loop, &out_watcher);
}
static void idle_cb(EV_P_ ev_idle *watcher, int revents) {
    static long idle_count = 0;
    fprintf(stderr, "idle: count = %ldn", ++idle_count);
    sleep(1); // simulate doing stuff
}
int main() {
    extern int errno;
    int master_fd;
    int sock_opt = 1;
    int conn_port = 7000;
    struct sockaddr_in addr;
    socklen_t addrlen;
    // **** the following is needed to set up a socket to receive data ****
    master_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (master_fd == -1) {
        perror("socket");
        return errno;
    }
    if (setsockopt(master_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &sock_opt, sizeof(sock_opt)) == -1) {
        perror("setsockopt");
        return errno;
    }
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(conn_port);
    addrlen = sizeof(addr);
    if (bind(master_fd, (struct sockaddr *) &addr, addrlen) != 0) {
        perror("bind");
        return errno;
    }
    if (listen(master_fd, 3) != 0) {
        perror("listen");
        return errno;
    }
    fprintf(stderr, "awaiting a connection on port %dn", conn_port);
    sock_fd = accept(master_fd, (struct sockaddr *) &addr, &addrlen);
    if (sock_fd == -1) {
        perror("accept");
        return errno;
    }
    fputs("in: connection establishedn", stderr);
    // **** end of socket setup code ****
    // define a loop
    loop = ev_default_loop(0);
    // define a repeating timer
    ev_timer_init (&timeout_watcher, timeout_cb, 5.0, 5.0);
    ev_timer_start (loop, &timeout_watcher);
    // define an idle process
    ev_idle_init(&idle_watcher, idle_cb);
    ev_idle_start (loop, &idle_watcher);
    // define the socket data receiver
    ev_io_init(&in_watcher, in_cb, sock_fd, EV_READ);
    ev_io_start (loop, &in_watcher);
    // define the socket data write complete watcher
    ev_io_init(&out_watcher, out_cb, sock_fd, EV_WRITE);
    // run the loop
    ev_run(loop, 0);
    // clean up
    close(sock_fd);
    close(master_fd);
    return 0;
}