简体   繁体   English

使用boost:asio与select? 阻止TCP输入或文件更新

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

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). 我打算在我的程序中有一个线程,它会等待两个文件描述符,一个用于套接字,另一个用于描述文件系统的FD(特别是等待查看是否有新文件添加到目录中)。 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. 由于我希望很少看到添加的新文件或新的TCP消息,我希望有一个线程等待输入和处理发生时检测到的任何输入,而不是单独的线程。

I then (finally!) got permission from the 'boss' to use boost. 然后我(终于!)获得了“老板”的许可,使用了boost。 So now I want to replace the basic sockets with boost:asio. 所以现在我想用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. 似乎asio对它自己的select版本进行了修改,而不是提供一个我可以直接使用select的FD。 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. 这让我不确定如何阻止这两个条件,新文件和TCP输入,同时当一个只使用select而另一个似乎不支持select的使用。 Is there an easy work around to this I'm missing? 有一个简单的工作,我错过了吗?

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. ASIO最好异步使用(这就是它的意思):你可以为TCP读取和文件描述符活动设置处理程序,并为你调用处理程序。

Here's a demo example to get you started (written for Linux with inotify support): 这是一个让您入门的演示示例(使用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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM