简而言之,有两种选择:
- 将代码更改为异步代码(
acceptor::async_accept() 和async_read),通过io_service::run() 在事件循环中运行,并通过io_service::stop() 取消。
- 使用信号等较低级别的机制强制阻塞调用中断。
我会推荐第一个选项,因为它更便于携带且更易于维护。要理解的重要概念是,只要有待处理的工作,io_service::run() 就会阻塞。当io_service::stop()被调用时,它会尝试让所有阻塞在io_service::run()上的线程尽快返回;它不会中断同步操作,例如acceptor::accept() 和socket::receive(),即使在事件循环中调用了同步操作。需要注意的是,io_service::stop() 是一个非阻塞调用,因此与在io_service::run() 上阻塞的线程的同步必须使用另一种机制,例如thread::join()。
这是一个运行 10 秒并监听 8080 端口的示例:
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <iostream>
void StartAccept( boost::asio::ip::tcp::acceptor& );
void ServerThreadFunc( boost::asio::io_service& io_service )
{
using boost::asio::ip::tcp;
tcp::acceptor acceptor( io_service, tcp::endpoint( tcp::v4(), 8080 ) );
// Add a job to start accepting connections.
StartAccept( acceptor );
// Process event loop.
io_service.run();
std::cout << "Server thread exiting." << std::endl;
}
void HandleAccept( const boost::system::error_code& error,
boost::shared_ptr< boost::asio::ip::tcp::socket > socket,
boost::asio::ip::tcp::acceptor& acceptor )
{
// If there was an error, then do not add any more jobs to the service.
if ( error )
{
std::cout << "Error accepting connection: " << error.message()
<< std::endl;
return;
}
// Otherwise, the socket is good to use.
std::cout << "Doing things with socket..." << std::endl;
// Perform async operations on the socket.
// Done using the socket, so start accepting another connection. This
// will add a job to the service, preventing io_service::run() from
// returning.
std::cout << "Done using socket, ready for another connection."
<< std::endl;
StartAccept( acceptor );
};
void StartAccept( boost::asio::ip::tcp::acceptor& acceptor )
{
using boost::asio::ip::tcp;
boost::shared_ptr< tcp::socket > socket(
new tcp::socket( acceptor.get_io_service() ) );
// Add an accept call to the service. This will prevent io_service::run()
// from returning.
std::cout << "Waiting on connection" << std::endl;
acceptor.async_accept( *socket,
boost::bind( HandleAccept,
boost::asio::placeholders::error,
socket,
boost::ref( acceptor ) ) );
}
int main()
{
using boost::asio::ip::tcp;
// Create io service.
boost::asio::io_service io_service;
// Create server thread that will start accepting connections.
boost::thread server_thread( ServerThreadFunc, boost::ref( io_service ) );
// Sleep for 10 seconds, then shutdown the server.
std::cout << "Stopping service in 10 seconds..." << std::endl;
boost::this_thread::sleep( boost::posix_time::seconds( 10 ) );
std::cout << "Stopping service now!" << std::endl;
// Stopping the io_service is a non-blocking call. The threads that are
// blocked on io_service::run() will try to return as soon as possible, but
// they may still be in the middle of a handler. Thus, perform a join on
// the server thread to guarantee a block occurs.
io_service.stop();
std::cout << "Waiting on server thread..." << std::endl;
server_thread.join();
std::cout << "Done waiting on server thread." << std::endl;
return 0;
}
在运行时,我打开了两个连接。这是输出:
10 秒后停止服务...
等待连接
用socket做事...
使用套接字完成,准备进行另一个连接。
等待连接
用socket做事...
使用套接字完成,准备进行另一个连接。
等待连接
立即停止服务!
正在等待服务器线程...
服务器线程退出。
在服务器线程上等待完成。