Joh*_*ing 7 c++ boost boost-asio
我已经修改了Boost asio教程的第3步,以便永远运行,并且每秒显示"tick"和"tock"而不是计数器:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
void print(const boost::system::error_code& /*e*/,
boost::asio::deadline_timer* t, int* count)
{
if( !((*count) % 2) )
std::cout << "tick\n";
else
std::cout << "tock\n";
++(*count);
t->expires_at(t->expires_at() + boost::posix_time::seconds(1));
t->async_wait(boost::bind(print,
boost::asio::placeholders::error, t, count));
}
int main()
{
boost::asio::io_service io;
int count = 0;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(1));
t.async_wait(boost::bind(print,
boost::asio::placeholders::error, &t, &count));
io.run();
std::cout << "Final count is " << count << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在我想异步地能够处理stdin上的按键.是否有一个io_service处理程序,我可以用它来响应按键,而不会阻塞睡眠或等待?
例如,我希望能够实现类似于以下的处理函数:
void handle_keypress(const boost::error_code&,
char c)
{
std::cout << "Tap '" << c << "'\n";
}
Run Code Online (Sandbox Code Playgroud)
我希望我对这个处理程序的调用是这样的:
char c = 0;
boost::asio::stdin_receiver sr(io);
st.async_wait(boost::bind(handle_keypress, boost::asio::placeholders::error, &c));
io.run();
Run Code Online (Sandbox Code Playgroud)
这是我可以使用内置服务处理程序或编写自己的asio吗?
我已经看到了这个问题,但是在应用答案中的链接代码只是这样做main
:
while (std::cin.getline(
Run Code Online (Sandbox Code Playgroud)
我正在编写的应用程序不是我上面概述的这个简单的tick-tock-tap Gizmo,但它将是一个多播服务器.几个工作线程将向组播组发送数据包,响应来自主线程的消息,并将消息发送回主线程.反过来,应用程序将由stdin的输入"驱动" - 例如,当用户按下"P"键时,多播广播将暂停,当命中"Q"时,整个事件将关闭.在主线程中,我将响应这些输入所做的就是向工作线程发送消息.
while
上面的循环在我的场景中不起作用,因为当它等待来自用户的stdin输入时,主线程将无法处理来自工作线程的消息.来自工作线程的一些消息将生成输出到stdout.
我不相信posix 聊天客户端使用 while 循环或 invokes std::getline
,这是您在我之前的答案中链接到的示例代码。也许你指的是另一个例子?在任何情况下,您都不需要使用io_service::dispatch
甚至单独的线程。流描述符的内置工具在这里工作得很好。请参阅我之前对类似问题的回答:使用 aposix::stream_descriptor
并分配STDIN_FILENO
给它。使用async_read
和处理读取处理程序中的请求。
我已经用一种方法修改了您的示例代码来完成此操作
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
void print(const boost::system::error_code& /*e*/,
boost::asio::deadline_timer* t, int* count)
{
if( !((*count) % 2) )
std::cout << "tick\n";
else
std::cout << "tock\n";
++(*count);
t->expires_at(t->expires_at() + boost::posix_time::seconds(1));
t->async_wait(boost::bind(print,
boost::asio::placeholders::error, t, count));
}
class Input : public boost::enable_shared_from_this<Input>
{
public:
typedef boost::shared_ptr<Input> Ptr;
public:
static void create(
boost::asio::io_service& io_service
)
{
Ptr input(
new Input( io_service )
);
input->read();
}
private:
explicit Input(
boost::asio::io_service& io_service
) :
_input( io_service )
{
_input.assign( STDIN_FILENO );
}
void read()
{
boost::asio::async_read(
_input,
boost::asio::buffer( &_command, sizeof(_command) ),
boost::bind(
&Input::read_handler,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
void read_handler(
const boost::system::error_code& error,
const size_t bytes_transferred
)
{
if ( error ) {
std::cerr << "read error: " << boost::system::system_error(error).what() << std::endl;
return;
}
if ( _command != '\n' ) {
std::cout << "command: " << _command << std::endl;
}
this->read();
}
private:
boost::asio::posix::stream_descriptor _input;
char _command;
};
int main()
{
boost::asio::io_service io;
int count = 0;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(1));
t.async_wait(boost::bind(print,
boost::asio::placeholders::error, &t, &count));
Input::create( io);
io.run();
std::cout << "Final count is " << count << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译、链接和运行
samm:stackoverflow samm$ g++ -I /opt/local/include stdin.cc -L /opt/local/lib -lboost_system -Wl,-rpath,/opt/local/lib
samm:stackoverflow samm$ echo "hello world" | ./a.out
command: h
command: e
command: l
command: l
command: o
command:
command: w
command: o
command: r
command: l
command: d
read error: End of file
tick
tock
tick
tock
tick
tock
tick
tock
tick
tock
^C
samm:stackoverflow samm$
Run Code Online (Sandbox Code Playgroud)
始终可以选择在单独的线程中处理 stdin 并通过io_service::dispatch将任何按键发布到主事件循环
该函数用于要求 io_service 执行给定的处理程序。
io_service 保证处理程序只会在当前正在调用 run()、run_one()、poll() 或 poll_one() 成员函数的线程中调用。