Асин c звонки не называются - PullRequest
0 голосов
/ 14 апреля 2020

У меня очень странная ошибка в моем коде, но я действительно не могу понять, в чем дело. Я пытаюсь реализовать очень простой клиент, который отправляет файл на сервер через сокет;

Файл отправляется следующим образом:

  1. Подключение к серверу
  2. Отправить заголовок с информацией о файле (имя и размер файла на данный момент)
  3. Пока доступны чанки
    1. Чтение фрагмента байтов из файла
    2. Отправить заголовок чанк.
    3. Отправка данных чанка

В Boost.Asio это становится:

  async_connect( // 1.
    async_write(   // 2.
      while (file)  // 3.
        async_write(  // 3.2
          async_write(  // 3.3
        )
    )
  )

Проблема в том, что Я никогда не достигаю 3.2 (функции, которые должны отправлять заголовок чанка). Кажется, что программа застряла. Я также пытаюсь поместить бросок внутрь, чтобы увидеть, что он имеет sh.

Ниже короткого фрагмента:

namespace net = boost::asio;
namespace fs = std::filesystem;
using net::ip::tcp;

class Client {
 public:
  Client(net::io_context &io_context, const tcp::resolver::results_type &endpoints) {
    net::async_connect(socket_, endpoints, [this](const auto &, auto) { sendMessageHeader(); });
  }

 private:
  void sendHeader() {
    // Prepare message
    // ...
    net::async_write(socket_, net::buffer(header_.data(), header_length()),
                     [this](const auto &, auto) { sendChunks(); });
  }

  void sendChunks() {
    // ...
    while(file) {
      // prepare the chunk header
      // ...
      chunkHeaderQueue_.push();
      chunkBufferQueue_.push();

      // send the header
      net::async_write(socket_, net::buffer(chunkHeaderQueue_.front().data(), chunkHeaderQueue_.front().size),
                       [this](const auto&, auto) {

                         auto &chunk = chunkBufferQueue_.front();
                         chunkHeaderQueue_.pop();
                         net::async_write(socket_, net::buffer(chunk), [this](const auto&, auto) {
                           chunkBufferQueue_.pop();
                         });
                       });
    }
  }

 private:
  boost::asio::io_context &io_context_;
  tcp::socket socket_;
  MessageHeader header_;
  ChunkHeaderQueue chunkHeaderQueue_;
  ChunkBufferQueue chunkBufferQueue_;
};

int main(int argc, char *argv[]) {
    // used for async operations
    net::io_context io_context;

    // resolver will connect to the server
    tcp::resolver resolver(io_context);
    auto endpoints = resolver.resolve(argv[1], argv[2]);

    // create the client and start all async operations
    Client client(io_context, endpoints, {argv[3]});

    // it will block until all async operation will be done!
    io_context.run();

  } catch (std::exception &e) {
    fmt::print("Exception: {}\n", e.what());
  }

  return 0;
}

1 Ответ

1 голос
/ 15 апреля 2020

В sendChuncks вы выполняете несколько операций записи в сокет, не ожидая завершения. Кроме того, вы получаете два раза из chunkBufferQueue_

Asyn c операции не должны использоваться следующим образом, они должны быть связаны, и ваша функция должна выглядеть так:

void sendChunk()
{
    auto& chunk = chunkBufferQueue_.front();
    net::async_write(socket_, net::buffer(chunck), 
    [this](const auto&, auto) {
        chunkBufferQueue_.pop();
        sendHeader();
    });
}

void sendHeader()
{
    if(!file)
        return;
    chunkHeaderQueue_.push();
    chunkBufferQueue_.push();

    auto& header = chunkHeaderQueue_.front();
    net::async_write(socket_, net::buffer(chunck), 
    [this](const auto&, auto) {
        chunkHeaderQueue_.pop();
        sendChunk();
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...