asio:服务器如何在监听客户端的同时主动向客户端发送信息?
asio :how does server actively send information to client while listening to client at the same time?
服务器接受新连接:
void do_accept()
{
acceptor_.async_accept(socket_,
[this](boost::system::error_code ec)
{
if (!ec)
{
connection_count++;
all_session.push_back(std::make_shared<session>(std::move(socket_), io_service_));
all_session.back()->start();
}
do_accept();
});
}
会话->开始的工作方式如下:
void start()
{
std::cout << "connection from " << socket_.remote_endpoint().address() << std::endl;
do_read_header();
}
do_read_header 处理消息然后递归调用自身。在处理消息时,它会调用 write 向客户端发送一些信息。
写函数如下:
void write(const chat_message& msg)
{
write_msgs_ = msg;
do_write(msg.length());
}
void do_write(std::uint32_t length)
{
auto self(shared_from_this());
boost::asio::async_write(socket_, boost::asio::buffer(write_msgs_.data(), length),
[this, self](boost::system::error_code ec, std::size_t /*length*/)
{
if (!ec)
{
do_read_header();
}
});
}
那么问题来了:服务端如何在do_read_header()递归之外主动向客户端发送信息?我需要服务器向所有客户端分派一些由未来用户输入决定的工作。
boost asio c++11 示例没有提到如何去做。我在上面找不到相关资源。
希望我能正确回答你的问题,你也想了解 asio 如何处理异步操作。
简而言之,一切都发生在 io_service
对象的 run
函数中。
当您在某个函数中调用 async_write
或 async_read
时,您注册了一个回调(当某些事件发生时将被调用),然后立即 return 到该函数。然后,当所有回调都注册后,它 returns in run
并等待事件。
所以我会尽量详细解释你的代码。方法 run
是一种无限循环,它检查事件是否已经发生。首先,您使用 acceptor_.async_accept
、return 到 run
注册回调并等待。当客户端连接时,accept 事件的回调被调用,你在 session->start
中用 boost::asio::async_read
注册一个回调(我猜是这个,因为你没有提供 do_read_header
源),注册再次在 do_accept
中回调,return 到 run
并等待新的客户端或数据。收到数据后,您调用 write
并使用 boost::asio::async_write
注册另一个回调,依此类推...最后仍然是 return 到 run
。
由于 run
是一个阻塞函数,如果您需要处理来自其他来源(例如服务器控制台)的输入,您可以执行以下操作之一:
1) 使用 run_one
代替 run
。编写自己的循环,其中调用 run_one
并处理其他操作。
2) 在另一个线程中调用run
(所有与io_service
关联的操作都将在该线程中处理),而在主线程中处理其他操作。一个小例子:
// here we process all network (or other) operations associated with io_service
void run( boost::asio::io_service& io_service ) {
while( true ) {
try {
io_service.run();
break; // run() exited normally
}
catch( std::exception& e) {
// Deal with exception as appropriate.
}
}
}
int main( ) {
...
boost::asio::io_service io_service;
...
// start io_service.run( ) in separate thread
auto t = std::thread( &run, std::ref( io_service ) );
...
while( true ) {
std::string line;
// read line from console
std::getline( std::cin, line );
// process input
if( line == "stop" ) {
io_service.stop( );
break;
} else {
send_to_everyone( line );
}
}
}
io_service
是线程安全的,所以你可以在主线程中安全地使用像 boost::asio::async_write
这样的异步操作(例如在 send_to_everyone
中)来注册其他回调和 write/read来自客户的数据。
服务器接受新连接:
void do_accept()
{
acceptor_.async_accept(socket_,
[this](boost::system::error_code ec)
{
if (!ec)
{
connection_count++;
all_session.push_back(std::make_shared<session>(std::move(socket_), io_service_));
all_session.back()->start();
}
do_accept();
});
}
会话->开始的工作方式如下:
void start()
{
std::cout << "connection from " << socket_.remote_endpoint().address() << std::endl;
do_read_header();
}
do_read_header 处理消息然后递归调用自身。在处理消息时,它会调用 write 向客户端发送一些信息。 写函数如下:
void write(const chat_message& msg)
{
write_msgs_ = msg;
do_write(msg.length());
}
void do_write(std::uint32_t length)
{
auto self(shared_from_this());
boost::asio::async_write(socket_, boost::asio::buffer(write_msgs_.data(), length),
[this, self](boost::system::error_code ec, std::size_t /*length*/)
{
if (!ec)
{
do_read_header();
}
});
}
那么问题来了:服务端如何在do_read_header()递归之外主动向客户端发送信息?我需要服务器向所有客户端分派一些由未来用户输入决定的工作。 boost asio c++11 示例没有提到如何去做。我在上面找不到相关资源。
希望我能正确回答你的问题,你也想了解 asio 如何处理异步操作。
简而言之,一切都发生在 io_service
对象的 run
函数中。
当您在某个函数中调用 async_write
或 async_read
时,您注册了一个回调(当某些事件发生时将被调用),然后立即 return 到该函数。然后,当所有回调都注册后,它 returns in run
并等待事件。
所以我会尽量详细解释你的代码。方法 run
是一种无限循环,它检查事件是否已经发生。首先,您使用 acceptor_.async_accept
、return 到 run
注册回调并等待。当客户端连接时,accept 事件的回调被调用,你在 session->start
中用 boost::asio::async_read
注册一个回调(我猜是这个,因为你没有提供 do_read_header
源),注册再次在 do_accept
中回调,return 到 run
并等待新的客户端或数据。收到数据后,您调用 write
并使用 boost::asio::async_write
注册另一个回调,依此类推...最后仍然是 return 到 run
。
由于 run
是一个阻塞函数,如果您需要处理来自其他来源(例如服务器控制台)的输入,您可以执行以下操作之一:
1) 使用 run_one
代替 run
。编写自己的循环,其中调用 run_one
并处理其他操作。
2) 在另一个线程中调用run
(所有与io_service
关联的操作都将在该线程中处理),而在主线程中处理其他操作。一个小例子:
// here we process all network (or other) operations associated with io_service
void run( boost::asio::io_service& io_service ) {
while( true ) {
try {
io_service.run();
break; // run() exited normally
}
catch( std::exception& e) {
// Deal with exception as appropriate.
}
}
}
int main( ) {
...
boost::asio::io_service io_service;
...
// start io_service.run( ) in separate thread
auto t = std::thread( &run, std::ref( io_service ) );
...
while( true ) {
std::string line;
// read line from console
std::getline( std::cin, line );
// process input
if( line == "stop" ) {
io_service.stop( );
break;
} else {
send_to_everyone( line );
}
}
}
io_service
是线程安全的,所以你可以在主线程中安全地使用像 boost::asio::async_write
这样的异步操作(例如在 send_to_everyone
中)来注册其他回调和 write/read来自客户的数据。