2016-04-17 3 views
1

Если кто-то может мне помочь, я не понимаю, как работает функция boost :: asio :: read в boost asio. В примере BOOST в них есть это объявить размер буфера до сообщения получено, которое не имеет смысла (как я знаю, сколько байт для чтения, прежде чем я прочитал сообщение?)boost :: asio :: read function hang

Я попробовал этот код, но он просто висит

boost::asio::io_service io_service; 

    tcp::resolver resolver(io_service); 
    tcp::resolver::query query(tcp::v4(), "localhost", "3000"); 
    tcp::resolver::iterator iterator = resolver.resolve(query); 

    tcp::socket sock(io_service); 
    boost::asio::connect(sock, iterator); 
    cout << "read start" << endl; 
    boost::system::error_code err_code; 

    // Read from client. 
    boost::asio::streambuf read_buffer; 
    int bytes_transferred = boost::asio::read(sock, read_buffer, err_code); 
    std::cout << "Read: " << make_string(read_buffer) << std::endl; 
    read_buffer.consume(bytes_transferred); // Remove data that was read. 
+0

Действительно ли это «повешение» или оно ожидает получения большего количества данных? – ForceBru

+0

ожидает, когда данные войдут, но как я могу сказать, сколько байтов читать до того, как я его прочитал? – flashc5

+0

Это отвратительный аспект сокетов (и TCP/IP). Они не могут сказать вам, сколько байтов данных является входящим. Вы должны использовать характер протокола, чтобы рассказать. Если вы создаете свой собственный протокол, у вас должен быть некоторый шаблон конца сообщения (например, «\ n») или заголовок сообщения, указывающий количество байтов. –

ответ

1

Как правило, вы знаете, сколько байтов вы хотите прочитать из определения протокола.

В противном случае вы должны прочитать байты по одному и наблюдать код ошибки, чтобы остановить в конце соединения, файл и т.д.

Синхронные методы (например read) в Boost.Asio хороши для кратких примеров, но в практических случаях вам следует предпочесть асинхронную версию async_read, которая позволяет вам отменить или просто ждать следующего фрагмента данных без блокировки вашей программы.

0

Я столкнулся с той же проблемой. Кажется, что boost :: asio :: read должен находиться там, пока подключенный клиент не будет закрыт. Вместо этого, вы можете использовать socket.read_some так:

using boost::asio::ip::tcp; 
try { 
    boost::asio::io_service io_service; 

    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 9999)); 

    for (;;) { 
     tcp::socket socket(io_service); 
     acceptor.accept(socket); 

     std::string message = "server received!\n"; 

     boost::system::error_code error_code; 
     boost::asio::streambuf stream_buf; 

     std::vector<char> buf(1024); 
     size_t len = socket.read_some(boost::asio::buffer(buf), error_code); 
     std::string received_filename(buf.begin(), buf.end()); 
     received_filename.resize(len); 
     if (error_code) { 
      std::cout << "error status: " << error_code.message() << std::endl; 
     } 

     boost::asio::write(socket, boost::asio::buffer(message), error_code); 
     if (error_code) { 
      std::cout << "error status: " << error_code.message() << std::endl; 
     } 
     query_database(tree, received_filename, output_folder, db_image_filenames); 
    } 
} 
catch (std::exception& e) { 
    std::cerr << e.what() << std::endl; 
} 

Это позволит получить сообщение от клиента сразу с относительно коротким сообщением. Надеюсь, эта помощь.