using boost:asio with select? blocking on TCP input OR file update

大城市里の小女人 提交于 2019-12-05 01:45:20

问题


I had intended to have a thread in my program which would wait on two file descriptors, one for a socket and a second one for a FD describing the file system (specifically waiting to see if a new file is added to a directory). Since I expect to rarely see either the new file added or new TCP messages coming in I wanted to have one thread waiting for either input and handle whichever input is detected when it occures rather then bothering with seperate threads.

I then (finally!) got permission from the 'boss' to use boost. So now I want to replace the basic sockets with boost:asio. Only I'm running into a small problem. It seems like asio implimented it's own version of select rather then providing a FD I could use with select directly. This leaves me uncertain how I can block on both conditions, new file and TCP input, at the same time when one only works with select and the other doesn't seem to support the use of select. Is there an easy work around to this I'm missing?


回答1:


ASIO is best used asynchronously (that's what it stands for): you can set up handlers for both TCP reads and the file descriptor activity, and the handlers would be called for you.

Here's a demo example to get you started (written for Linux with inotify support):

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <sys/inotify.h>

namespace asio = boost::asio;
void start_notify_handler();
void start_accept_handler();

// this stuff goes into your class, only global for the simplistic demo
asio::streambuf buf(1024);
asio::io_service io_svc;
asio::posix::stream_descriptor stream_desc(io_svc);
asio::ip::tcp::socket sock(io_svc);
asio::ip::tcp::endpoint end(asio::ip::tcp::v4(), 1234);
asio::ip::tcp::acceptor acceptor(io_svc, end);

// this gets called on file system activity
void notify_handler(const boost::system::error_code&,
                    std::size_t transferred)
{
    size_t processed = 0;
    while(transferred - processed >= sizeof(inotify_event))
    {
        const char* cdata = processed
                            + asio::buffer_cast<const char*>(buf.data());
        const inotify_event* ievent =
                                 reinterpret_cast<const inotify_event*>(cdata);
        processed += sizeof(inotify_event) + ievent->len;
        if(ievent->len > 0 && ievent->mask & IN_OPEN)
            std::cout << "Someone opened " << ievent->name << '\n';
    }
    start_notify_handler();
}

// this gets called when nsomeone connects to you on TCP port 1234
void accept_handler(const boost::system::error_code&)
{
    std::cout << "Someone connected from " 
              << sock.remote_endpoint().address() << '\n';
    sock.close(); // dropping connection: this is just a demo
    start_accept_handler();
}

void start_notify_handler()
{
    stream_desc.async_read_some( buf.prepare(buf.max_size()),
        boost::bind(&notify_handler, asio::placeholders::error,
                    asio::placeholders::bytes_transferred));
}

void start_accept_handler()
{
    acceptor.async_accept(sock,
        boost::bind(&accept_handler, asio::placeholders::error));
}

int main()
{
    int raw_fd = inotify_init(); // error handling ignored
    stream_desc.assign(raw_fd);
    inotify_add_watch(raw_fd, ".", IN_OPEN);
    start_notify_handler();
    start_accept_handler();
    io_svc.run();
}


来源:https://stackoverflow.com/questions/12272666/using-boostasio-with-select-blocking-on-tcp-input-or-file-update

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!