0

我有兴趣收听传入的连接,当没有活动连接时我想做后台处理。我还没有找到这两者的任何例子。

我想做类似这样的事情:

从一个例子:

//ev_io callback

static void server_cb(EV_P_ ev_io *w, int revents)
{
  //Accept new client connection
  //Read from client socket

  //stop event loop
  ev_io_stop(EV_A_ &client->io);

  //send back to client

  //start event loop again
  ev_io_start(EV_A_ &client->io);

}

main()
{
  // To be sure that we aren't actually blocking
  ev_periodic_init(&every_few_seconds, not_blocked, 0, 5, 0);
  ev_periodic_start(EV_A_ &every_few_seconds);

  // Get notified whenever the socket is ready to read
  ev_io_init(&server.io, server_cb, server.fd, EV_READ);
  ev_io_start(EV_A_ &server.io);

 }

现在在这个例子中,我应该在哪里添加空闲事件以及应该在何时何地启动和停止空闲事件,这样它就不会干扰主事件处理程序,并且应该只在它空闲时调用。

谢谢。

4

2 回答 2

1

好吧,我也是 libev 的新手,但我将这个简单的服务器演示放在一起,该服务器在套接字上接收数据同时还处理超时和空闲事件。

#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;
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 = %d\n", t);
    if (r == 0) {
        fputs("in: connection closed\n", 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");
    }
}

static void timeout_cb(EV_P_ ev_timer *watcher, int revents) {
    fprintf(stderr, "timeout: now = %f\n", ev_now(loop));
}

static void idle_cb(EV_P_ ev_idle *watcher, int revents) {
    static long idle_count = 0;
    fprintf(stderr, "idle: count = %ld\n", ++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 %d\n", conn_port);
    sock_fd = accept(master_fd, (struct sockaddr *) &addr, &addrlen);
    if (sock_fd == -1) {
        perror("accept");
        return errno;
    }
    fputs("in: connection established\n", 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);

    // run the loop
    ev_run(loop, 0);

    // clean up
    close(sock_fd);
    close(master_fd);
    return 0;
}
于 2013-05-15T18:34:51.710 回答
0

您应该在调用用于进入主循环的 ev_loop() 之前添加 ev_idle。(实际上,你可以在任何你想要的地方添加它。但是对于上述情况,我认为它是可以的。)

只有当没有其他事件挂起时,才会调用您与空闲观察者绑定的回调。它不会干扰任何其他事件的回调。回调将按顺序调用。

顺便说一句,我建议你在 libev 中小心使用空闲事件。因为如果你不控制它,它会消耗整个cpu。定期事件会更好。如果你想使用它(例如在计算密集型程序中),最好在一次回调中做一件小事。这样它就会将控件放回主循环以响应其他事件。(例如 io 事件)

PS:您不必在 server_cb 回调中调用 ev_io_stop 并再次调用 ev_io_start 。因为回调根本不会受到干扰。

于 2013-09-17T03:09:22.920 回答