Rectangle 27 6

Asio can be used without Boost if the following conditions are met:

  • C++11 (or later) compiler in C++11 (or later) compile mode. Exactly how to enable this mode varies based on compiler. For GCC/clang use the -std=c++11 flag. For Xcode set the C++ language dialect to C++11 or later in project settings
  • Asio headers are downloaded from think-async.com. Asio is not part of the standard library (yet). It is bundled with Boost and is available standalone from the authors website. How exactly to add Asio to your include path varies based on compiler. For GCC/clang use -I/path/to/asio or place the Asio headers in /use/local/include. Xcode will also read /usr/local/include or you can specify a custom header path in the header search paths section of your project config.
  • #define ASIO_STANDALONE before including Asio headers. This define tells Asio to use the C++11 standard library features for things like error codes, shared pointers, etc rather than using Boost's polyfills.

c++ - How to use Asio standalone in Xcode C++11 without Boost - Stack ...

c++ xcode c++11 boost-asio
Rectangle 27 3

The error is occurring in an operation on sock, not acceptor. Thus, acceptor's state should not be affected. It just requires initiating an async_accept operation with sock being in its initial closed state.

Here is a complete basic example that listens on port 12345:

#include <iostream>

#include <boost/array.hpp>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

class tcp_reader
{
public:
  tcp_reader(boost::asio::io_service& io_service)
    : io_service_(io_service),
      socket_(io_service),
      acceptor_(io_service, 
                tcp::endpoint(tcp::v4(), 12345))
  {
    accept_connection();
  }

private:

  void accept_connection()
  {
    std::cout << "accepting connection" << std::endl;
    // Verify socket is in a closed state.
    socket_.close();
    // On success or failure, acceptor will open() socket_.
    acceptor_.async_accept(socket_,
      boost::bind(&tcp_reader::handle_accept, this,
                  boost::asio::placeholders::error));
  }

  void handle_accept(const boost::system::error_code& error)
  {
    // On error, return early.
    if (error)
    {
      std::cout << "handle_accept: " << error.message() << std::endl;
      return;
    }

    // Start reading from socket.
    read();    
  }

  void read()
  {
    std::cout << "reading from socket" << std::endl;
    async_read(socket_, boost::asio::buffer(buffer_),
      boost::asio::transfer_at_least(1),
      boost::bind(&tcp_reader::handle_read, this,
                  boost::asio::placeholders::error,
                  boost::asio::placeholders::bytes_transferred));
  }

  void handle_read(const boost::system::error_code& error,
                   std::size_t bytes_transferred)
  {
    // On error, go back to listening for a new connection.
    if (error)
    {
      std::cout << "handle_read: " << error.message() << std::endl;
      accept_connection();
      return;
    }

    // Output read data.
    std::cout.write(&buffer_[0], bytes_transferred);

    // Read data, so read some more.
    read(); 
  }

private:
  boost::asio::io_service& io_service_;
  tcp::socket              socket_;
  tcp::acceptor            acceptor_;
  boost::array<char, 1024> buffer_;
};

int main()
{
  boost::asio::io_service io_service;
  tcp_reader reader(io_service);
  io_service.run();
}

When using it, I ran it in one terminal, and connected to port 12345, send messages, killed connection, then reestablished a connection. The server console output was as follows:

and the client console:

One behavioral detail of which to be aware is that although an async_accept operation may not be pending on the acceptor_, connections are still being queued. Thus, if a connection has already been accepted, and another client tries to connect, then the latter client will have its connection pending to be accepted. If this is not the desired behavior, then the acceptor needs to transition out of a listening state via close(). This answer diagrams state transitions and describes some of the acceptor behavior in more detail.

c++ - boost::asio acceptor reopen and async read after EOF - Stack Ove...

c++ sockets boost c++11 boost-asio
Rectangle 27 2

You are using blocking calls assuming a direct 1-1 ratio of client->server calls (and vice-versa), but that is almost certainly not going to be the case in a real world application. In reality, the application is going to receive portions of the TCP stream in numerous calls to receive from both the client and the server. You can handle this in two distinct ways. Using select() to see what sockets need to have data read from them, or using an asynchronous library to facilitate the reading/writing to/from the client/server sockets for you.

Or, here's an example for writing one in boost. There are many other examples if you google "boost::asio proxy server".

thanks. it worked. I was doing the src and running the b2 install based on the documentation on their site. but no luck with that one. this works though.

sockets - C++ linux proxy server communications - Stack Overflow

c++ sockets
Rectangle 27 0

What simple C POD types can be taken from boost::asio::ip::tcp::socket that could be later reinterpreted with assign()?

socket::native() returns the native representation of what was passed to socket::assign(). On Linux and Mac OS X this is an integer, I don't know about Windows.

c++ - Boost::asio::socket how to get int or uint from it that would be...

c++ sockets boost boost-asio
Rectangle 27 0

Although I wasn't able to find a way to query an ostream to determine the amount of data 'waiting' in the stream directly, I was able to avoid ostreams entirely and serialize the data into a char* array. This can then be sent in a similar way to the old-style C socket method with the boost::asio::write() function:

...
tcp::socket socket(io_service);
char * buffer = new char[size];  // or a smart-ptr
float_array.SerializeToArray(static_cast<void*>(buffer, size));
void * p = static_cast<void*>(buffer);
int bytes_sent = boost::asio::write(socket, boost::asio::buffer(p, bytes_to_send);

Alternatively, if the use of boost::asio::streambuf and std::ostream are preferred, then it appears that the streambuf can be queried (with .size()) after the ostream has been used to write some data:

boost::asio::streambuf b;
std::ostream os(&b);
float_array.SerializeToOstream(&os);

// send a chunk of a particular size
int bytes_to_send = std::min(chunk_size, b.size());
cout << b.size() << endl;  // shows amount of remaining data
boost::asio::write(socket, b, boost::asio::transfer_exactly(bytes_to_send));
cout << b.size() << endl;  // shows a reduction in amount of remaining data

So if this is invoked multiple times (for each chunk), then the ostream, the streambuf and the io_service need to be kept in scope.

c++ - Writing sections of data to TCP socket with boost::asio::ip::tcp...

c++ tcp boost-asio protocol-buffers iostream