从套接字和STDIN中提升Asio多线程

时间:2013-01-23 08:18:26

标签: c++ multithreading boost-asio

我想简单地让一个聊天客户端从套接字和boost::asio::posix::stream_descriptor分配给stdin异步监听。

如果我在单线程应用程序中运行此代码,则一切正常。

如果我从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();
}
}

我做错了什么?

1 个答案:

答案 0 :(得分:1)

根据boost::asio::posix::stream_descriptor的文档,从多个线程使用相同的实例是不安全的。在多线程情况下,通常将处理程序包装成一行以进行序列化。

在您的情况下,我没有看到为同一客户端连接使用多个线程的重点。