Question

Rant: I really dislike boost::asio, So I've been looking at alternatives and came across libev. Which seems simple enough for me, but is doing a few things I cannot understand. If those are too many questions in one thread, please let me know.

1) I set the listening socket to NON_BLOCK, I also set each accepted incoming connection as NON_BLOCK, yet somewhere in the code the socket(s) turns into BLOCK. Ex:

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;
}

I have tried to make the main loop also not to block:

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

But it doesnt seem to have made a different. PLEASE DO NOT redirect me to the documentation (the only available source of documentation on the internet) I have read it.

I do this for the client socket that has been accepted:

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);

Yet every time my read callback is executed, the socket is magically set to BLOCK

2) I have tried setting a timeout for the socket: 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");

(Taken from here: this question) It simply doesn't work. Is this because the sockets are reset to BLOCKing mode ?

3) I have seen a C++ wrapper for libev. I absolutely hate the fact I have to make the callbacks static functions, it ruins everything for me. Yet all the examples I have seen use:

signal.loop.break_loop();

and

loop.run(0);

which, funnily enough produces:

error: ‘struct ev::loop_ref’ has no member named ‘break_loop’ error: ‘struct ev::default_loop’ has no member named ‘run’

on Debian Squeeze.

So, what I am asking is:

  1. What, who, where is the socket changed from NON_BLOCK to BLOCK ?
  2. How (if) can I set a timeout for the socket (blocking or non-blocking)
  3. What is wrong with ev++.h and why are those nice people using the wrappers I can't use?

Please, bear in mind that I can use the sockets to read and send data, but in a blocking manner, without timeouts. Furthermore, as this is a server, I NEED to keep the code in classes, as I have to save messages per connected clients. Making this static or non-class methods simply ruins it, or forces me to take a very different approach.

PS: Any alternatives to libev ?

Was it helpful?

Solution

You aren't setting the client FD to non-blocking mode. You are setting the listening socket FD.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top