Discussion:
[asio-users] Sending data over TLS with ASIO (Standalone)
Sandra Schreiner
2016-02-02 18:49:21 UTC
Permalink
Hello,

Currently I'm looking into sending data with ASIO. I understand that io_service is a abstraction of the underlying
OS-dependend IO functionality and that the run() call will poll all outstanding handles in the asio queue and finishs
afterwards.

But looking at the SSL example of asio (see below for my code) I don't know how I can manage to keep the connection
(or session) open and read and write data over this connection outside of the normal 'workflow' of the client.
That means: if I call my send() method of the client right in handle_handshake the message is send. But if I try to call c.send()
from my main method, nothing happens after "Client Handshake success".

Why is send() handled different in the descriped scenario? Is io_service already finished?
I also tried using asio::io_service::work work(io_service); but the client still does nothing after the handshake.
How can I create an simple interface to send data to the server on demand?

Many thanks for any help in advance.

Best regards,
Sandra

PS: My code shown below (server and session as in example provided my asio standalone)
-------------------------------------------------------------------------------------------
class client
{
public:
client(asio::io_service& io_service,
asio::ssl::context& context,
asio::ip::tcp::resolver::iterator endpoint_iterator)
: socket_(io_service, context) {
socket_.set_verify_mode(asio::ssl::verify_peer);
socket_.set_verify_callback(
std::bind(&client::verify_certificate, this, std::placeholders::_1, std::placeholders::_2));

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

bool verify_certificate(bool preverified,
asio::ssl::verify_context& ctx){
return true;
}

void handle_connect(const asio::error_code& error){

if (!error){
std::cout << "Client Connect success "<< "\n";
socket_.async_handshake(asio::ssl::stream_base::client,
std::bind(&client::handle_handshake, this,
std::placeholders::_1));
}
else {
std::cout << "Client Connect failed: " << error.message() << "\n";
}
}

void handle_handshake(const asio::error_code& error){
if (!error) {
std::cout << "Client Handshake success "<< "\n";
//send("test") no send here
}
else{
std::cout << "Client Handshake failed: " << error.message() << "\n";
}
}


void send(char * request_){
std::cout << " Client Sende daten "<< "\n";
size_t request_length = strlen(request_);

asio::async_write(socket_,
asio::buffer(request_, request_length),
std::bind(&client::handle_write, this,
std::placeholders::_1,
std::placeholders::_2));
}

void handle_write(const asio::error_code& error, size_t bytes_transferred){
if (!error)
{
std::cout << " Client Write success "<< "\n";
asio::async_read(socket_,
asio::buffer(reply_, bytes_transferred),
std::bind(&client::handle_read, this,
std::placeholders::_1,
std::placeholders::_2));
}
else {
std::cout << "Client Write failed: " << error.message() << "\n";
}
}

void handle_read(const asio::error_code& error, size_t bytes_transferred) {
if (!error) {
std::cout << "Client Reply: ";
std::cout.write(reply_, bytes_transferred);
std::cout << "\n";
}
else {
std::cout << "Client Read failed: " << error.message() << "\n";
}
}

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

using namespace std;

int main(){

std::thread t {
[](){
asio::io_service server_service;
server s(server_service, 8877);
server_service.run();
}
};

std::this_thread::sleep_for(std::chrono::milliseconds(3000));
asio::io_service io_service;

asio::ip::tcp::resolver resolver(io_service);
asio::ip::tcp::resolver::query query("127.0.0.1", std::to_string(8877));
asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);

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

client c(io_service, ctx, iterator);
c.send("test");
io_service.run();

t.join();

return 0;
}
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140
_______________________________________________
asio-users mailing list
asio-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/asio-users
_______________________________________________
Using Asio? List your project at
http://think-async.com/Asio/WhoIsUsingAsio
Bjorn Reese
2016-02-02 22:31:17 UTC
Permalink
Post by Sandra Schreiner
But looking at the SSL example of asio (see below for my code) I don't know how I can manage to keep the connection
(or session) open and read and write data over this connection outside of the normal 'workflow' of the client.
That means: if I call my send() method of the client right in handle_handshake the message is send. But if I try to call c.send()
from my main method, nothing happens after "Client Handshake success".
No asynchronous operations are executed until you call io_service::run()
so the c.send() method fails because you have scheduled both an
async_connect() and an async_write() before you start the io_service.
This means that asio will try to execute async_write() before doing
the (still unscheduled) handshake.


------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140
_______________________________________________
asio-users mailing list
asio-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/asio-users
_______________________________________________
Using Asio? List your project at
http://think-async.com/Asio/WhoIsUsingAsio
Dale Wilson
2016-02-02 23:21:04 UTC
Permalink
Your server side thread creates an io_service with no active requests, then
calls run on it. Since there is nothing to do, io_service::run() exits, so
the thread exits and nothing happens.


- You should
- Create an io_service
- Create an asio::work attached to the service
- Then you can call run().
- An alternate approach is:
- Create an io_service
- Add a listen request.
- Call run
- Be sure that EVERY handler adds a new request to the io_service
before exiting.
- Your handle_handshake method does not add a new request so
the io_service::run() call returns with nothing to do, so
the thread
exits(). If you have a handler like this you must use the
"asio::work"
approach.

Dale
Post by Sandra Schreiner
Hello,
Currently I'm looking into sending data with ASIO. I understand that
io_service is a abstraction of the underlying
OS-dependend IO functionality and that the run() call will poll all
outstanding handles in the asio queue and finishs
afterwards.
But looking at the SSL example of asio (see below for my code) I don't
know how I can manage to keep the connection
(or session) open and read and write data over this connection outside of
the normal 'workflow' of the client.
That means: if I call my send() method of the client right in
handle_handshake the message is send. But if I try to call c.send()
from my main method, nothing happens after "Client Handshake success".
Why is send() handled different in the descriped scenario? Is io_service already finished?
I also tried using asio::io_service::work work(io_service); but the client
still does nothing after the handshake.
How can I create an simple interface to send data to the server on demand?
Many thanks for any help in advance.
Best regards,
Sandra
PS: My code shown below (server and session as in example provided my asio standalone)
-------------------------------------------------------------------------------------------
class client
{
client(asio::io_service& io_service,
asio::ssl::context& context,
asio::ip::tcp::resolver::iterator endpoint_iterator)
: socket_(io_service, context) {
socket_.set_verify_mode(asio::ssl::verify_peer);
socket_.set_verify_callback(
std::bind(&client::verify_certificate, this,
std::placeholders::_1, std::placeholders::_2));
asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
std::bind(&client::handle_connect, this,
std::placeholders::_1));
}
bool verify_certificate(bool preverified,
asio::ssl::verify_context& ctx){
return true;
}
void handle_connect(const asio::error_code& error){
if (!error){
std::cout << "Client Connect success "<< "\n";
socket_.async_handshake(asio::ssl::stream_base::client,
std::bind(&client::handle_handshake, this,
std::placeholders::_1));
}
else {
std::cout << "Client Connect failed: " << error.message() << "\n";
}
}
void handle_handshake(const asio::error_code& error){
if (!error) {
std::cout << "Client Handshake success "<< "\n";
//send("test") no send here
}
else{
std::cout << "Client Handshake failed: " << error.message() << "\n";
}
}
void send(char * request_){
std::cout << " Client Sende daten "<< "\n";
size_t request_length = strlen(request_);
asio::async_write(socket_,
asio::buffer(request_, request_length),
std::bind(&client::handle_write, this,
std::placeholders::_1,
std::placeholders::_2));
}
void handle_write(const asio::error_code& error, size_t
bytes_transferred){
if (!error)
{
std::cout << " Client Write success "<< "\n";
asio::async_read(socket_,
asio::buffer(reply_, bytes_transferred),
std::bind(&client::handle_read, this,
std::placeholders::_1,
std::placeholders::_2));
}
else {
std::cout << "Client Write failed: " << error.message() << "\n";
}
}
void handle_read(const asio::error_code& error, size_t
bytes_transferred) {
if (!error) {
std::cout << "Client Reply: ";
std::cout.write(reply_, bytes_transferred);
std::cout << "\n";
}
else {
std::cout << "Client Read failed: " << error.message() << "\n";
}
}
asio::ssl::stream<asio::ip::tcp::socket> socket_;
char request_[max_length];
char reply_[max_length];
};
using namespace std;
int main(){
std::thread t {
[](){
asio::io_service server_service;
server s(server_service, 8877);
server_service.run();
}
};
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
asio::io_service io_service;
asio::ip::tcp::resolver resolver(io_service);
asio::ip::tcp::resolver::query query("127.0.0.1",
std::to_string(8877));
asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
asio::ssl::context ctx(asio::ssl::context::sslv23);
ctx.load_verify_file("ca.pem");
client c(io_service, ctx, iterator);
c.send("test");
io_service.run();
t.join();
return 0;
}
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140
_______________________________________________
asio-users mailing list
https://lists.sourceforge.net/lists/listinfo/asio-users
_______________________________________________
Using Asio? List your project at
http://think-async.com/Asio/WhoIsUsingAsio
--
Dale Wilson
Principal Software Engineer
Object Computing, Inc.
Loading...