1
我只想讓一個聊天客戶端異步地從套接字偵聽,並從boost::asio::posix::stream_descriptor
分配給stdin。從套接字和STDIN提升ASIO多線程
如果我在單線程應用程序中運行此代碼,所有工作正常。
如果我從2個或更多線程調用io_service.run()
,那麼來自stdin的異步操作永遠不會好,但仍會執行來自套接字的異步讀取。
這裏是代碼:
MasterClient::MasterClient(boost::asio::io_service& io_service,boost::asio::ip::tcp::resolver::iterator iter, string nickName)
:it(iter),chatNick(nickName)
{
this->fdIn_ = str_ptr(new boost::asio::posix::stream_descriptor(io_service,::dup(STDIN_FILENO)));
this->dirServer_ = new(connectedPeer);
this->dirServer_->sock = socket_ptr(new boost::asio::ip::tcp::socket(this->io_service_));
boost::asio::async_connect(*(this->dirServer_->sock), this->it,
boost::bind(&MasterClient::connectionHandler, this,
boost::asio::placeholders::error));
}
主:
int main(int argc, const char * argv[])
{
boost::asio::io_service io_service(2);
boost::asio::io_service::work work(io_service);
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(argv[1], argv[2]);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
string nick;
cout << "Inserire un nickname per la sessione di chat: " << flush;
getline(cin,nick);
MasterClient cli(io_service,iterator,nick);
cli.run();
}
和MasterClient :: run()的
void MasterClient::run()
{
// Create a pool of threads to run all of the io_services.
std::vector<boost::shared_ptr<boost::thread> > threads;
boost::asio::io_service::work work(this->io_service_);
for (std::size_t i = 0; i < 1; ++i)
{
boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_)));
threads.push_back(thread);
}
// Wait for all threads in the pool to exit.
for (std::size_t i = 0; i < threads.size(); ++i)
threads[i]->join();
}
這裏我所說的異步讀數:
void MasterClient::clientDelegate()
{
if(this->connectToServer())
{
this->mainMenu();
boost::asio::async_read_until(*fdIn_, inBuff_, '\n',
boost::bind(&MasterClient::fdInMenuHandler,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
(*(this->dirServer_->sock)).async_read_some(boost::asio::buffer(this->buff_),
boost::bind(&MasterClient::serverHandler,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
this->dirServer_->sock));
this->io_service_.post(boost::bind(&MasterClient::printer,this));
}else
{
if(this->isDebugging)
cout << "Error in ClientDelegate." << endl;
}
if(this->isDebugging)
cout << "ClientDelegate END" << endl;
}
連接處理程序,其中clientDelegate被調用:
void MasterClient::connectionHandler(const boost::system::error_code& error)
{
cout << "connected" << endl;
try
{
if(error)
throw boost::system::system_error(error);
else
{
this->dirServer_->endpoint = boost::asio::ip::tcp::endpoint((*(this->dirServer_->sock)).remote_endpoint());
this->clientDelegate();
}
}catch(const boost::system::system_error& e)
{
cerr << "Boost Exception in ConnectHandler ---> " << e.what() << endl;
this->io_service_.stop();
}
}
我到底做錯了什麼?
根據boost asio文檔,如果我將io_service.run調用到多個線程中,那些線程有資格調用處理程序。我錯了嗎? –
是的,從多個線程調用同一個io_service的run方法是安全的。然而,處理程序可以同時調用,所以你需要小心。 Asio提供的鏈可以幫助您在多線程程序中連續處理程序。 – jcm
目前還不清楚你的程序鏈是如何處理的。 clientDelegate在哪裏打電話? fdInMenuHandler做什麼?在一個客戶端連接中使用多線程看起來很奇怪。爲什麼不單線程? – jcm