20 Mayıs 2018 Pazar

asio async_read metodu

Giriş
Açıklaması şöyle.
This operation is implemented in terms of zero or more calls to the stream's async_read_some function, and is known as a composed operation.
Açıklaması şöyle.
async_read() will read until either the buffers are full or an error occurs. If the read handler is being invoked with neither of these conditions being satisfied, then one potential culprit is that undefined behavior has been invoked.
Açıklaması şöyle.
This function is used to asynchronously read a certain number of bytes of data from a stream. The function call always returns immediately. The asynchronous operation will continue until one of the following conditions is true:
  • The supplied buffers are full. That is, the bytes transferred is equal to the sum of the buffer sizes.
  • An error occurred.
İmzası
İmzası şöyle. İkinci parametre aslında MutableBufferSequence tipinden
template<
        typename AsyncReadStream,
        typename MutableBufferSequence,
        typename ReadHandler>
    void-or-deduced async_read(
        AsyncReadStream & s,
        const MutableBufferSequence & buffers,
        ReadHandler handler);
İçi Nasıldır
Aslında döngü içinde async_read_some metodunun çağrılmasıdır. İçi şöyledir.
for (;;)
{
  stream_.async_read_some(buffers_, ASIO_MOVE_CAST(read_op)(*this));

  buffers_.consume(bytes_transferred);
  total_transferred_ += bytes_transferred;

  if (!ec && bytes_transferred == 0)
    break;
}

Tamamlama Seçeneği
Sadece stream socketler için kullanılır.

Belirtilmemiş
Eğer tamamlanma seçeneği belirtilmemişse belirtilen byte sayısı doluncaya kadar okumaya çalışır. Yani metodun için şöyledir.
boost::asio::async_read(
    s, buffers,
    boost::asio::transfer_all(), // this is the completion condition
    handler);
Elimde iki dekişken olsun.
enum { max_length = 1024 };
char request[max_length];
Şöyle yaparız.
ba::async_read(s,
               ba::buffer(request, max_length),
               handler);
transfer_at_least
Şöyle yaparız.
boost::asio::async_read(s,
                        buffers,
                        boost::asio::transfer_at_least(1),
                        handler);
transfer_exactly
Elimde iki değişken olsun.
long m_readPayloadLength;
boost::asio::streambuf m_buffer;
Şöyle yaparız.
boost::asio::async_read(s,
        m_buffer,
        boost::asio::transfer_exactly(sizeof(m_readPayloadLength)),
        handler);
Klasik Handler metodu
handler metodun imzası şöyledir.
void handler (
  const boost::system::error_code& error, // Result of operation.

  std::size_t bytes_transferred           // Number of bytes copied into the
                                          // buffers. If an error occurred,
                                          // this will be the  number of
                                          // bytes successfully transferred
                                          // prior to the error.
);
Lambda kullanabiliriz. Şöyle yaparız.
[this, self](boost::system::error_code ec, size_t length) {
  if (ec) {
    ...
  }
  else {
    ...
});
Hata Durumu
EOF açıklaması şöyle
The end of a stream can cause readasync_readread_until or async_read_until functions to violate their contract. E.g. a read of N bytes may finish early due to EOF. An EOFerror may be used to distinguish the end of a stream from a successful read of size 0.
Hata çeşidini kontrol etmek için şöyle yaparız.
void handler(const boost::system::error_code& errorCode,
  std::size_t bytesTransferred)
{
  //Check for the errors
  if (errorCode)
  {
    if ((errorCode.value() == boost::asio::error::connection_reset))
    {
      ...
    } 
    else if (errorCode.value() == boost::asio::error::eof)
    {
      ...
    }
    else if (errorCode.value() != boost::asio::error::operation_aborted)
    {
      ...
    }
    return;
  }
  //No errors
  ...
}

Hata varsa socket kapatılabilir. Şöyle yaparız.
if (ec) {
  socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
  socket.close();
  ...
}
else {
  ...
}
Kapatılan nesne bir listeden silinebilir. Şöyle yaparız.
list.Remove (shared_from_this());
Farklı Handler metodu
Kullanılan buffer'da handler'a geçilebilir. Şöyle yaparız.
void handler(shared_ptr<std::vector<unsigned char>> buf, 
             const boost::system::error_code& ec, 
             size_t bytes_transferred)
{
...
}
async_read - socket + std::vector
Şöyle yaparız.
auto buf = make_shared<std::vector<unsigned char>>(1 * 1024 * 1024);

boost::asio::async_read(socket,
        boost::asio::buffer(buf),
        handler
);
async_read - socket future
Şöyle yaparız.
auto send_result = async_write(input_socket, out_buffer, use_future);
auto send_status = send_result.wait_for(std::chrono::seconds(timeout));
if(send_status == std::future_status::timeout)
{
    //error
}

out_buffer.consume(request.length());

Hiç yorum yok:

Yorum Gönder