ChrisInEdmonton
ChrisInEdmonton

Reputation: 4578

Simple C/C++ network I/O library

I have the following problem to solve. I want to make a number of requests to a number of "remote" servers (actually, a server farm we control). The connection is very simple. Send a line, and then read lines back. Because of the number of requests and the number of servers, I use pthreads, one for each request.

The naive approach, using blocking sockets, does not work; very occasionally, I'll have a thread stuck in 'connect'. I cannot use SIGALRM because I am using pthreads. I tried converting the code to O_NONBLOCK but this vastly complicated the code to read single lines.

What are my options? I'm looking for the simplest solution that allows the following pseudocode:


// Inside a pthread
try {
    req = connect(host, port);
    req.writeln("request command");
    while (line = req.readline()) {
        // Process line
    }
} catch TimeoutError {
    // Bitch and complain
}

My code is in C++ and I'm using Boost. A quick look at Boost ASIO shows me that it probably isn't the correct approach, but I could be wrong. ACE is far, far too heavy-weight to solve this problem.

Upvotes: 1

Views: 2866

Answers (4)

user224579
user224579

Reputation: 437

You mentioned this happens 'very occasionally'. Your 'connect' side should have the fault tolerance and error handling you are looking for but you should also consider the stability of your servers, DNS, network connections, etc.

The underlying protocols are very sturdy and work very well, so if you are experiencing these kind of problems that often then it might be worth checking.

Upvotes: 1

Norman
Norman

Reputation: 519

You may also be able close the socket from the other thread. That should cause the connect to fail.

Upvotes: 0

ZZ Coder
ZZ Coder

Reputation: 75496

Have you looked at libevent?

http://www.monkey.org/~provos/libevent/

It's totally different paradigm but the performance is so amazing.

memcached is built on top of libevent.

Upvotes: 6

coelhudo
coelhudo

Reputation: 5080

I saw the comments and i think you can use boost::asio with boost::asio::deadline_timer

Fragment of a code:

    void restart_timer()
    {
       timer_.cancel();
       timer_.expires_from_now(boost::posix_time::seconds(5));
       timer_.async_wait(boost::bind(&handleTimeout,
       MyClass::shared_from_this(), boost::asio::placeholders::error));
    }

Where handleTimeout is a callback function, timer_ is boost::asio::deadline_timer and MyClass is similar to

    class Y: public enable_shared_from_this<Y>
    {
     public:

     shared_ptr<Y> f()
     {
       return shared_from_this();
     }
    }

You can call restart_timer before connect ou read/write

More information about share_from_this()

Upvotes: 5

Related Questions