I'm trying to develop an app that realises the communication between a gameserver and an applcation.

My code so far is:

#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

using namespace std;

enum { max_length = 1024 };

class client
{
    public:

        boost::asio::streambuf receive_buffer;

        client(boost::asio::io_service& io_service, boost::asio::ssl::context& context, boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
    : socket_(io_service, context)
      {
        socket_.set_verify_mode(boost::asio::ssl::verify_peer);
        socket_.set_verify_callback(
            boost::bind(&client::verify_certificate, this, _1, _2));

        boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
            boost::bind(&client::handle_connect, this,
              boost::asio::placeholders::error));
      }

    bool verify_certificate(bool preverified, boost::asio::ssl::verify_context& ctx)
    {
        char subject_name[256];
        X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
        X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);

        return preverified;
    }

    void handle_connect(const boost::system::error_code& error)
    {
        if (!error)
        {
            socket_.async_handshake(boost::asio::ssl::stream_base::client,
            boost::bind(&client::handle_handshake, this,
            boost::asio::placeholders::error));
        }
        else
        {
            cout << "Connect failed: " << error.message() << "\n";
        }
    }

    void handle_handshake(const boost::system::error_code& error)
    {
        if (!error)
        {
            cout << "trimite cmd: ";
            cin.getline(request_, max_length);
            size_t request_length = strlen(request_);

            boost::asio::async_write( socket_,
                    boost::asio::buffer(request_, request_length),
                        boost::bind(&client::handle_write, this,
                            boost::asio::placeholders::error,
                                boost::asio::placeholders::bytes_transferred));

        }
        else
        {
            cout << "Handshake failed: " << error.message() << "\n";
        }
    }

    void handle_write(const boost::system::error_code& error, size_t bytes_transferred)
    {
        if (!error)
        {
            boost::asio::async_read_until(socket_,
            receive_buffer,
            "!",
            boost::bind(&client::handle_read, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));

        }
        else
        {
            cout << "Write failed: " << error.message() << "\n";
        }
    }

    void handle_read( const boost::system::error_code& error, size_t bytes_transferred )
    {
        if( !error )
        {

            cout << "de la sv: " << &receive_buffer << "\n";
        }
        else
        {
            cout << "Read failed: " << error.message() << "\n";
        }
    }

    private:
        boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
        char request_[max_length];
        char reply_[max_length];
};

int main( int argc, char* argv[] )
{
    if (argc != 3)
    {
        cerr << "Usage: client <host> <port>\n";
        return 1;
    }

    boost::asio::io_service io_service;

    boost::asio::ip::tcp::resolver resolver(io_service);
    boost::asio::ip::tcp::resolver::query query(argv[1], argv[2]);
    boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);

    boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
    ctx.load_verify_file("ca.pem");

    client c( io_service, ctx, iterator );

    io_service.run();
}

This is the example from the Boost site. My problem is that i want to make the connection "keep-alive" and separate it in "threads" to call it like that, and dont know if its the appropiate word.

e.g.:

in the main() i start the io_service then i should have 1 callback for ReceiveingData, and also one Function to Send Data.

Client can receive data permanently( i use here read_until ) but also he can send data anytime he wants.

These actions are done until i call the close of the socket.

for e.g.

client sends data 1
client sends data 2
client receives data 213( ReceiveingData is fired )
client receives data 125161( ReceiveingData is fired )
client receives data 136161( ReceiveingData is fired )
10 minutes pause
client sends data xxxx
client receives data zzz( ReceiveingData is fired )
SOCKET CLOSE, client disconnected from server
How to deal with this? I read something about "strand" but i don't understand what's that.

I tried to do something with strand but i have a bunch of errors:

#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/asio/strand.hpp>

#include <fstream>

using namespace std;

boost::asio::streambuf receive_buffer;

enum { max_length = 1024 };

class client
{
    public:

    client(boost::asio::io_service& io_service, boost::asio::ssl::context& context, boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
    : strand_(io_service), socket_(io_service, context)
      {
        socket_.set_verify_mode(boost::asio::ssl::verify_peer);
        socket_.set_verify_callback(
            boost::bind(&client::verify_certificate, this, _1, _2));

        boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
              boost::bind(&client::handle_connect, this,
              boost::asio::placeholders::error));
      }

    bool verify_certificate(bool preverified, boost::asio::ssl::verify_context& ctx)
    {
        char subject_name[256];
        X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
        X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);

        return preverified;
    }

    void handle_connect(const boost::system::error_code& error)
    {
        if (!error)
        {
            socket_.async_handshake(boost::asio::ssl::stream_base::client,
             boost::bind(&client::handle_handshake, this,
            boost::asio::placeholders::error));
        }
        else
        {
            cout << "Connect failed: " << error.message() << "\n";
        }
    }

    void read( )
    {
        boost::asio::async_read_until(socket_,
            receive_buffer,
            "!",
             strand_.wrap(&handle_read));
    }

    void write( )
    {
        cout << "trimite cmd: ";
            cin.getline(request_, max_length);
            size_t request_length = strlen(request_);

            boost::asio::async_write( socket_,
                    boost::asio::buffer(request_, request_length),
                         strand_.wrap(&handle_write));
    }

    void handle_handshake(const boost::system::error_code& error)
    {
        if (!error)
        {
            strand_.post(&read);
            strand_.post(&write);
        }
        else
        {
            cout << "Handshake failed: " << error.message() << "\n";
        }
    }

    void handle_write(const boost::system::error_code& error, size_t bytes_transferred)
    {
        if (!error)
        {
            write( );
        }
    }

    void handle_read( const boost::system::error_code& error, size_t bytes_transferred )
    {
        if( !error )
        {
            ofstream f;

            f.open( "test.txt", ios::app );

            f << &receive_buffer << endl;

            f.close( );

            read( );
        }
    }

    private:
        boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
        boost::asio::io_service::strand strand_;
        char request_[max_length];
        char reply_[max_length];
};

int main( int argc, char* argv[] )
{
    if (argc != 3)
    {
        cerr << "Usage: client <host> <port>\n";
        return 1;
    }

    boost::asio::io_service io_service;

    boost::asio::ip::tcp::resolver resolver(io_service);
    boost::asio::ip::tcp::resolver::query query(argv[1], argv[2]);
    boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);

    boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
    ctx.load_verify_file("ca.pem");

    client c( io_service, ctx, iterator );

    io_service.run();
}
Re: Boost Asio TCP SSL Concurrent Read Write 80 80

You need to post your errors and where they are coming from if you want any reasonable help. Asking for people to analyze 250+ lines of code is not usually received well. In any case I don't have time as I am currently out of the country until after the first of the year and have little time for such.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of 1.18 million developers, IT pros, digital marketers, and technology enthusiasts learning and sharing knowledge.