0

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();
}
2
Contributors
1
Reply
49
Views
7 Months
Discussion Span
Last Post by rubberman
1

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.

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.