6

1 つはソケット用、もう 1 つはファイル システムを記述する FD 用です (具体的には、新しいファイルがディレクトリに追加されるかどうかを確認するために待機します)。新しいファイルが追加されたり、新しい TCP メッセージが着信したりすることはめったにないと予想されるので、別のスレッドに煩わされるのではなく、1 つのスレッドが入力を待機し、発生したときに検出された入力を処理する必要がありました。

その後、(ついに!)「ボス」からブーストを使用する許可を得ました。そこで、基本的なソケットをboost:asioに置き換えたいと思います。私だけが小さな問題に直面しています。selectで直接使用できるFDを提供するのではなく、asioがselectの独自のバージョンを実装したようです。これにより、新しいファイルとTCP入力の両方の条件でブロックする方法がわかりません。同時に、一方が選択でのみ機能し、もう一方が選択の使用をサポートしていないようです。私が行方不明になっているこれに対する簡単な回避策はありますか?

4

1 に答える 1

8

ASIO は非同期で使用するのが最適です (これがその略です)。TCP 読み取りとファイル記述子アクティビティの両方に対してハンドラーを設定でき、ハンドラーが呼び出されます。

これは、開始するためのデモ例です (inotify をサポートする Linux 用に記述されています)。

#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();
}
于 2012-09-05T03:45:13.387 に答える