2013-12-18 8 views
3

В повышении :: ASIO standardexamples после async_accept()socket объекта двигается к session объекту (который обрабатывает все async_read() вызов) инициализации его следующим образом:повышения :: ASIO :: async_read 100% загрузка процессора на простом примере

std::make_shared<session>(std::move(socket_))->start(); 

И при построении session он снова движущуюся (не правда ли reduntantly?):

session(tcp::socket socket) 
    : socket_(std::move(socket)) 

Затем чтение от клиента производится следующим образом:

boost::asio::async_read(socket_, ... 

И все идет хорошо. Но когда я пытаюсь сделать async_read() не с объекта session, а непосредственно с async_accept() и использовать его socket объект, CPU поднимается до 100% сразу после подключения клиента. Зачем?

#include <boost/asio.hpp> 
using boost::asio::ip::tcp; 

class Server 
{ 
public: 
    Server(boost::asio::io_service& io_service, 
     const tcp::endpoint& endpoint)  
    : acceptor_(io_service, endpoint), 
     socket_(io_service) 
    { 
    do_accept(); 
    } 

private: 
    void do_accept() 
    { 
    acceptor_.async_accept(socket_, 
     [this](boost::system::error_code ec) 
     { 
     if (!ec) { 
      char* buf = new char[5]; 
      boost::asio::async_read(socket_, 
       boost::asio::buffer(buf, 5), 
       [this, buf](boost::system::error_code ec, std::size_t) 
       { 
       if (!ec) { 
        std::cout.write(buf, 5); 
        std::cout << std::endl; 
       } 
       delete[] buf; 
       }); 
     } 
     do_accept(); 
     }); 
    } 

    tcp::acceptor acceptor_; 
    tcp::socket socket_; 
}; 

int main(int argc, char* argv[]) 
{ 
    int port = 22222; 
    boost::asio::io_service io_service; 
    tcp::endpoint endpoint(tcp::v4(), port); 
    new Server(io_service, endpoint); 
    io_service.run(); 
} 

подталкивания 1,49

EDIT

Спасибо за ответы! Я в конечном итоге, перемещая socket_ перед использованием:

tcp::socket *socket = new tcp::socket(std::move(socket_)); 

Кроме того, та же проблема обсуждается на Repeated std::move on an boost::asio socket object in C++11

ответ

3

Если контакт равный не был открыт, то он будет открыт во время операции async_accept(). В противном случае, если peer уже открыт, то обработчик будет отправлен в io_service для вызова с кодом ошибки boost::asio::error::already_open. Следовательно, посланной код вызывает плотную асинхронную цепочку вызовов на форму:

  1. Операция async_accept() вызывается в первый раз, в результате чего socket_ должны быть открыто.
  2. Обработчик async_accept() вызывает do_accept(), инициируя операцию async_accept().
  3. socket_ уже открыт, что приводит к тому, что операция async_accept() отправляет свой обработчик в io_service с ошибкой boost::asio::error::already_open.
  4. Асинхронная цепочка вызовов начинается с шага 2.

Такое поведение не наблюдается в официальных примерах, поскольку socket's move operator приводит к тому, перемещенный-из объекта, чтобы быть в том же состоянии, как если бы она была построена с использованием basic_stream_socket(io_service&) конструктора. Таким образом, перемещенный объект находится в закрытом состоянии и готов к принятию.

1

Вы с использованием одной socket_ во всех местах, поэтому, когда соединение принято, обработчик вызовов do_accept() снова, который использует тот же socket_, то это снова и снова принял ...

Вы, вероятно, нужно всегда использовать новый сокет, как показано ниже:

void do_accept() 
    { 
    boost::shared_ptr<tcp::socket> psocket(new tcp::socket(io_service)); 
    acceptor_.async_accept(*psocket, boost::bind(&Server::handleAccept, this, psocket, _1)); 
    } 

    void handleAccept(boost::shared_ptr<tcp::socket> psocket, const boost::system::error_code& ec) 
    { 
    if (!ec) { 
    char* buf = new char[5]; 
    boost::asio::async_read(
     *psocket, 
     boost::asio::buffer(buf, 5), 
     [this, buf](boost::system::error_code ec, std::size_t) 
     { 
     if (!ec) { 
      std::cout.write(buf, 5); 
      std::cout << std::endl; 
     } 
     delete[] buf; 
     }); 
    } 
    do_accept(); 
    } 
Смежные вопросы