25 Eylül 2017 Pazartesi

asio read metodu

Giriş
Tüm asio.hpp dosyasını dahil etmek istemiyorsak şu satırı dahil ederiz.
#include <boost/asio/read.hpp>
Açıklaması şöyle
The call will block 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.
  • The completion_condition function object returns 0.
Bir başka açıklama şöyle
boost::asio::read() will read until
a) all 100 bytes has been read, or
b) there is an error, or
c) there is an end-of-stream condition.

It is a compound operation. One of the effects of that is that it can both return an error and have read some data.

For example, if 50 bytes are read and then the stream enters an eof condition, the bytes_transferred will be 50 and the error_code returned will indicate end of file.

With a compound operation it's important to check the bytes_transferred before you check the error.
Örnek
Eğer büyüklüğü 0 olan bir buffer ile read() çağrısı yaparsak sonuç olarak 0 alırız. Yani 0 byte okuyabilmiştir. Şöyle yaparız. error_code değşikeni bir hata belirtmez.
int header_size_ = 30000;
error_code ec;
vector<char> v;

tcp::socket socket = ...;

const auto bTransfer = asio::read(socket, asio::buffer(headerBytesBuf),
                                transfer_exactly(header_size_), ec);

if (ec) {
  std::cerr << ec.message();
}
read - std::array
Şöyle yaparız.
std::array<char, 128> buf;
size_t len = asio::read(socket,asio::buffer(buf));
read - char []
Şöyle yaparız.
char buf [1024];
size_t length = boost::asio::read(sock, boost::asio::buffer(buf,1024));
read - streambuf + error_code
Şöyle yaparız.
asio::streambuf sb;
boost::system::error_code ec;
asio::read(socket, sb, ec);
std::cout << std::addressof(sb);
read - streambuf + error_code + transfer_at_least
Şöyle yaparız.
boost::asio::streambuf buf;
boost::system::error_code ec;
size_t length = asio::read(socket, buf,bboost::asio::transfer_at_least(10), ec)

if (length)) {...}
read - streambuf + error_code + transfer_exactly
Şöyle yaparız
std::error_code ec;
size_t length = asio::read(socket, buf, asio::transfer_exactly(10), ec);
Şöyle yaparız.
boost::system::error_code ec;

io_service svc;
tcp::socket s(svc);
s.connect(tcp::endpoint(address_v4::loopback(), 6767));

streambuf sb;
auto transferred = read(s, sb, transfer_exactly(1020), ec);

std::cerr << "read " << transferred << " till " << ec.message() << "\n";
read - std::vector
Örnek
Şöyle yaparız.
int header_size_ = 30000;
error_code ec;
vector<char> v;
v.resize(header_size_);

const auto bTransfer = read(socket, buffer(v),
                           transfer_exactly(header_size_), ec);
Örnek
Şöyle yaparız. Burada aslında bir eksiklik var, read() işleminin döndürdüğü değere bakılmıyor ancak bakmakta fayda var.
std::string str;

boost::system::error_code ec;

std::vector<char> v;

while (!error) {
  int bytes_read = ba::read(socket, ba::buffer(v), error);
  std::copy(buf.begin(), buf.begin() + bytes_read, std::back_inserter(str));
  if (bytes_read == 0)
    break;
}
Hata Ele Alma
Örnek
Şöyle yaparız.
boost::system::error_code ec;
size_t length = boost::asio::read(socket,..., ec);
if (ec == boost::asio::error::eof) {
  //ends here if the host app closes the socket
  //log error & return
}

if (length <= 0) {  //log error & return
}
Örnek
Şöyle yaparız.
boost::system::error_code e;
size_t len = boost::asio::read(socket, boost::asio::buffer(inBuffer), e);
if (e == boost::asio::error::eof)
{
  ...; //Socket is closed
}
else if (e) //Instead of checking read data length, check error variable
{
  throw boost::system::system_error(e); //Propagate error up
}
timeout
Şöyle yaparız. Eğer okuma gerçekleştiyse read_result değişkenine errror_code  değeri atanır. Metod sonunda read_result hata kodu içeriyorsa exception fırlatılır. Okuma işlemi gerçekleşmediyse timer expire edince okuma işlemi iptal edilir.
template <typename SyncReadStream, typename MutableBufferSequence>
void readWithTimeout(SyncReadStream& s,
  const MutableBufferSequence& buffers,
  const boost::asio::deadline_timer::duration_type& expiry_time)
{
  boost::optional<boost::system::error_code> timer_result;
  boost::asio::deadline_timer timer(s.get_io_service());
  timer.expires_from_now(expiry_time);
  timer.async_wait([&timer_result] (const boost::system::error_code& error)
  {
    timer_result.reset(error); 
  });

  boost::optional<boost::system::error_code> read_result;
  boost::asio::async_read(s, buffers, [&read_result]
    (const boost::system::error_code& error, size_t)
  {
    read_result.reset(error);
  });

  s.get_io_service().reset();
  while (s.get_io_service().run_one())
  { 
    if (read_result)
      timer.cancel();
    else if (timer_result)
      s.cancel();
  }

  if (*read_result)
    throw boost::system::system_error(*read_result);
}


Hiç yorum yok:

Yorum Gönder