Boost logo

Boost Users :

Subject: [Boost-users] [asio] Incorrect reporting of bytes transferred in write handler in 1.54
From: Darren (darodo_at_[hidden])
Date: 2013-07-11 02:18:36


Is anybody else seeing problems with the bytes_transferred reported to the
write_handler after a successful async_write?

I am seeing a value of zero despite the fact that the peer receives the
bytes and no error is reported to the write_handler.

My example code when built against 1.54 exhibits the problem whereas
building against 1.53 works correctly.

I am running on Windows 7 with MSVC 2010.

A couple of notes:

* I only see the problem when the number of threads is > 1, even though the
handlers are invoked on a strand.

* Defining BOOST_ASIO_DISABLE_IOCP makes everything work properly.

When running my code a failure shows itself like this:

Client: Writing value 85
Server: Received 4 bytes, value 85
Client: bytesWritten = 0

In other words, the client used async_write to send 4 bytes with long value
85 the server. The server received these bytes. The client write_handler
was called with no error but a bytes_transferred value of 0.

Is there something I don't understand or is this a problem introduced in
1.54?

#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>

using namespace boost::asio;

const std::size_t NumThreads = 2;
const unsigned short Port = 12345;

// Prevent interleaved output
boost::mutex logMutex;

struct Server
{
   Server(io_service& svc) :
      m_socket(svc),
      m_acceptor(svc, ip::tcp::endpoint(ip::tcp::v4(), Port)),
      m_buffer(0)
   { }
   
   void Run()
   {
      m_acceptor.accept(m_socket);

      // Simple blocking reads
      while(std::size_t bytesRead =
         read(m_socket, buffer(&m_buffer, sizeof(m_buffer))))
      {
         boost::mutex::scoped_lock lock(logMutex);
         std::cout << "Server: Received " << bytesRead
            << " bytes, value " << m_buffer << std::endl;
      }
   }

   ip::tcp::socket m_socket;
   ip::tcp::acceptor m_acceptor;
   unsigned long m_buffer;
};

struct Client
{
   Client(io_service& svc) :
      m_strand(svc),
      m_socket(svc),
      m_buffer(0)
   {
      m_socket.connect(
         ip::tcp::endpoint(ip::address_v4::from_string("127.0.0.1"), Port));

      ScheduleWrite();
   }

   void WriteHandler(const boost::system::error_code& err,
                     std::size_t bytesWritten)
   {
      assert(!err);

      if(bytesWritten != sizeof(m_buffer))
      {
         boost::mutex::scoped_lock lock(logMutex);
         std::cout << "Client: bytesWritten = " << bytesWritten <<
std::endl;
         return;
      }

      ScheduleWrite();
   }

   void ScheduleWrite()
   {
      {
         boost::mutex::scoped_lock lock(logMutex);
         std::cout << "Client: Writing value " << ++m_buffer << std::endl;
      }

      async_write(m_socket, buffer(&m_buffer, sizeof(m_buffer)),
         m_strand.wrap(
            std::bind(&Client::WriteHandler, this,
               std::placeholders::_1, std::placeholders::_2)));
   }

   io_service::strand m_strand;
   ip::tcp::socket m_socket;
   unsigned long m_buffer;
};

int main(int argc, char* argv[])
{
   boost::asio::io_service svc;

   Server server(svc);
   Client client(svc);

   boost::thread_group threads;

   for(int n = 0; n < NumThreads; ++n)
      threads.create_thread(std::bind(&io_service::run, &svc));

   server.Run();

   return 0;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net