используя boost: asio с выбором? блокировка на входе TCP или обновление файла

Я намеревался иметь поток в моей программе, который ожидал бы два файловых дескриптора, один для сокета и второй для FD, описывающего файловую систему (особенно ожидая, чтобы увидеть, добавлен ли новый файл в каталог). Поскольку я ожидаю редко видеть либо добавленный новый файл, либо новые поступающие TCP-сообщения, я хотел, чтобы один поток ожидал ввода или обрабатывал любой обнаруженный ввод, когда он происходит, а не беспокоился об отдельных потоках.

Затем я (наконец!) Получил разрешение от «босса» на использование наддува. Итак, теперь я хочу заменить базовые сокеты на boost: asio. Только я сталкиваюсь с небольшой проблемой. Кажется, что asio реализовал собственную версию select, а не предоставил FD, который я мог бы использовать непосредственно с select. Это оставляет меня неуверенным, как я могу заблокировать оба условия, новый файл и ввод TCP, в то же время, когда один работает только с select, а другой, кажется, не поддерживает использование select. Есть ли легкая работа вокруг этого я скучаю?

5

Решение

ASIO лучше всего использовать асинхронно (это то, что он обозначает): вы можете настроить обработчики как для чтения TCP, так и для действия файлового дескриптора, и обработчики будут вызваны для вас.

Вот демонстрационный пример для начала (написанный для Linux с поддержкой inotify):

#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();
}
7

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]