I expected the code below to print Hello, world! every 5 seconds, but what happens is that the program pauses for 5 seconds and then prints the message over and over with no subsequent pauses. What am I missing?
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::asio;
using namespace std;
io_service io;
void print(const boost::system::error_code& /*e*/)
{
cout << "Hello, world!\n";
deadline_timer t(io, boost::posix_time::seconds(5));
t.async_wait(print);
}
int main()
{
deadline_timer t(io, boost::posix_time::seconds(5));
t.async_wait(print);
io.run();
return 0;
}
edit to add working code below. thanks guys.
#include <iostream>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::asio;
using namespace std;
class Deadline {
public:
Deadline(deadline_timer &timer) : t(timer) {
wait();
}
void timeout(const boost::system::error_code &e) {
if (e)
return;
cout << "tick" << endl;
wait();
}
void cancel() {
t.cancel();
}
private:
void wait() {
t.expires_from_now(boost::posix_time::seconds(5));
t.async_wait(boost::bind(&Deadline::timeout, this, boost::asio::placeholders::error));
}
deadline_timer &t;
};
class CancelDeadline {
public:
CancelDeadline(Deadline &d) :dl(d) { }
void operator()() {
string cancel;
cin >> cancel;
dl.cancel();
return;
}
private:
Deadline &dl;
};
int main()
{
io_service io;
deadline_timer t(io);
Deadline d(t);
CancelDeadline cd(d);
boost::thread thr1(cd);
io.run();
return 0;
}
You're creating the deadline_timer as a local variable and then immediately exiting the function. This causes the timer to destruct and cancel itself, and calls your function with an error code which you ignore, causing the infinite loop.
Using a single timer object, stored in a member or global variable, should fix this.
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::asio;
using namespace std;
io_service io;
deadline_timer t(io, boost::posix_time::seconds(5));
void print(const boost::system::error_code& /*e*/)
{
cout << "Hello, world!\n";
t.expires_from_now(boost::posix_time::seconds(5));
t.async_wait(print);
}
int main()
{
//deadline_timer t(io, boost::posix_time::seconds(5));
t.async_wait(print);
io.run();
return 0;
}
If you look at the error code, you're getting operation cancelled errors.
Related
Is there a nice way of splitting the following sample C++ code in source and header such that all the users of the server don't need to indirectly include headers that are really only needed for the server's internals ?
Source listing for Daytime.3
//
// server.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <ctime>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
std::string make_daytime_string()
{
using namespace std; // For time_t, time and ctime;
time_t now = time(0);
return ctime(&now);
}
class tcp_connection
: public boost::enable_shared_from_this<tcp_connection>
{
public:
typedef boost::shared_ptr<tcp_connection> pointer;
static pointer create(boost::asio::io_service& io_service)
{
return pointer(new tcp_connection(io_service));
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
message_ = make_daytime_string();
boost::asio::async_write(socket_, boost::asio::buffer(message_),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
private:
tcp_connection(boost::asio::io_service& io_service)
: socket_(io_service)
{
}
void handle_write(const boost::system::error_code& /*error*/,
size_t /*bytes_transferred*/)
{
}
tcp::socket socket_;
std::string message_;
};
class tcp_server
{
public:
tcp_server(boost::asio::io_service& io_service)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), 13))
{
start_accept();
}
private:
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.get_io_service());
acceptor_.async_accept(new_connection->socket(),
boost::bind(&tcp_server::handle_accept, this, new_connection,
boost::asio::placeholders::error));
}
void handle_accept(tcp_connection::pointer new_connection,
const boost::system::error_code& error)
{
if (!error)
{
new_connection->start();
}
start_accept();
}
tcp::acceptor acceptor_;
};
int main()
{
try
{
boost::asio::io_service io_service;
tcp_server server(io_service);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
Most examples I can find assume all the code will be in a single file, for some reason.
The question might seem stupid, but every time I try to refactor this, some template decides to crash. I could really use the example.
The general answer to this is to use Pimpl Idiom. You can make the header as simple as
#pragma once
#include <memory>
class tcp_server {
public:
tcp_server();
~tcp_server();
void run();
private:
struct impl;
std::unique_ptr<impl> _pimpl;
};
Then main.cpp can be:
#include "server.h"
#include <iostream>
int main()
{
try {
tcp_server server;
server.run();
} catch (std::exception const& e) {
std::cerr << e.what() << std::endl;
}
}
Of course, that leaves the question how you implement test.cpp:
tcp_server::tcp_server() : _pimpl(std::make_unique<impl>()) {}
void tcp_server::run() { _pimpl->run(); }
And all the logic has been moved to the implementation type and all local functions can have file linkage.
Live Demo
Live On Wandbox
File test.cpp
#include "server.h"
#include <iostream>
int main()
{
try {
tcp_server server;
server.run();
} catch (std::exception const& e) {
std::cerr << e.what() << std::endl;
}
}
File server.h
#pragma once
#include <memory>
class tcp_server {
public:
tcp_server();
~tcp_server();
void run();
private:
struct impl;
std::unique_ptr<impl> _pimpl;
};
File server.cpp
#include "server.h"
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <ctime>
#include <string>
using boost::asio::ip::tcp;
namespace /*anonymous, file linkage*/ {
static std::string make_daytime_string()
{
using namespace std; // For time_t, time and ctime;
time_t now = time(0);
return ctime(&now);
}
class tcp_connection
: public boost::enable_shared_from_this<tcp_connection> {
public:
typedef boost::shared_ptr<tcp_connection> pointer;
static pointer create(boost::asio::any_io_executor executor)
{
return pointer(new tcp_connection(executor));
}
tcp::socket& socket() { return socket_; }
void start()
{
message_ = make_daytime_string();
boost::asio::async_write(
socket_, boost::asio::buffer(message_),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
private:
tcp_connection(boost::asio::any_io_executor executor)
: socket_(executor)
{
}
void handle_write(const boost::system::error_code& /*error*/,
size_t /*bytes_transferred*/)
{
}
tcp::socket socket_;
std::string message_;
};
} // namespace
struct tcp_server::impl {
void run() { io_service_.run(); }
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.get_executor());
acceptor_.async_accept(new_connection->socket(),
boost::bind(&impl::handle_accept, this,
new_connection,
boost::asio::placeholders::error));
}
void handle_accept(tcp_connection::pointer new_connection,
const boost::system::error_code& error)
{
if (!error) {
new_connection->start();
}
start_accept();
}
boost::asio::io_service io_service_;
tcp::acceptor acceptor_{io_service_, tcp::endpoint(tcp::v4(), 13)};
};
tcp_server::tcp_server() : _pimpl(std::make_unique<impl>()) {}
tcp_server::~tcp_server() = default;
void tcp_server::run() { _pimpl->run(); }
I'm newbie here, so if I have any errors just tell me.
The problem is that I have two processes and I want them to execute concurrently because they take too much time. So I thought to implement a class timer which manage its own boost::asio::io_service and create a thread for this io_service. The code is the following:
timer.hpp
#include <iostream>
#include <string>
#include <functional>
#include <thread>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
class timer
{
public:
timer(std::function<void(void)> task,
int time)
: io__(),
timer__(io__, boost::posix_time::milliseconds(time)),
repetitive_task__(task),
time_wait__(time)
{
timer__.async_wait(boost::bind(&timer::loop, this));
}
void start()
{
thread__ = std::thread([this](){
io__.run();
});
thread__.join();
}
void loop()
{
repetitive_task__();
timer__.expires_at(timer__.expires_at() + boost::posix_time::milliseconds(time_wait__));
timer__.async_wait(boost::bind(&timer::loop, this));
}
void stop()
{
timer__.cancel();
io__.stop();
}
private:
boost::asio::io_service io__;
boost::asio::deadline_timer timer__;
std::function<void(void)> repetitive_task__;
int time_wait__;
std::thread thread__;
};
For testing it, I have the simplest main I could think:
main.cpp
#include "timer.hpp"
void test1()
{
printf("action1 \n");
}
void test2()
{
printf("action 2 \n");
}
int main(int argc, char* argv[])
{
timer timer1(&test1, 100);
timer timer2(&test2, 50);
timer1.start();
timer2.start();
return 0;
}
And the result is always action1. Never action2.
I've been looking for how to implement timers properly like in this post or in this example of boost, but I still don't understand what I am doing wrong.
Thanks in advance
I am trying to use the boost process (0.5) library.
In asych_io.cpp example, the read handler is not getting called even once.
even after io_service.run() is called.
I am using Linux.
#include <boost/process.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <string>
using namespace boost::process;
using namespace boost::process::initializers;
using namespace boost::iostreams;
boost::process::pipe create_async_pipe()
{
return create_pipe();
}
int main()
{
boost::process::pipe p = create_async_pipe();
file_descriptor_sink sink(p.sink, close_handle);
child c = execute(
run_exe(search_path("nasm")),
set_cmd_line("nasm -v"),
bind_stdout(sink)
);
file_descriptor_source source(p.source, close_handle);
typedef boost::asio::posix::stream_descriptor pipe_end;
boost::asio::io_service io_service;
pipe_end pend(io_service,p.source);
boost::array<char, 4096> buffer;
boost::asio::async_read(pend, boost::asio::buffer(buffer),
[&](const boost::system::error_code&, std::size_t bytes_transferred){
std::cout << std::string(buffer.data(), bytes_transferred) << std::flush;
});
io_service.run();
}
After I replaced
boost::asio::async_read(pend...
with
pend.async_read_some(...
It worked for me.
I want to implement a mechanism that allows me to block program flow until an async operation has completed. (Mostly to be used in unit tests where there is no message loop.)
The code I have creates a thread and waits for a condition notification inside the thread:
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <thread>
struct Blocker {
Blocker() :
wait_thread([this]() {
std::mutex mtx;
std::unique_lock<std::mutex> lck(mtx);
cond.wait(lck);
})
{
}
void wait() { wait_thread.join(); }
void notify() { cond.notify_one(); }
std::condition_variable cond;
std::thread wait_thread;
};
template<typename Callback>
void async_operation(const Callback & cb) { cb(); }
int main() {
Blocker b;
async_operation([&](){ b.notify(); });
b.wait();
}
The problem is that it often deadlocks because the call to notify occurs before the thread even started. How should I fix this?
#include <mutex>
#include <condition_variable>
struct blocker
{
blocker () : done (false) {}
void
notify ()
{
std::unique_lock<std::mutex> lock (m);
done = true;
c.notify_all ();
}
void
wait ()
{
std::unique_lock<std::mutex> lock (m);
while (!done)
c.wait (lock);
}
bool done;
std::mutex m;
std::condition_variable c;
};
I made a static-lib. And I created this three classes in
Connection Class
#ifndef _CONNECTION_H_
#define _CONNECTION_H_
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include <memory>
#include "ByteBuffer.h"
class Connection: public boost::enable_shared_from_this<Connection>
{
public:
typedef boost::shared_ptr<Connection> pointer;
explicit Connection(boost::asio::io_service& io_service);
virtual ~Connection();
boost::asio::ip::tcp::socket& socket();
virtual void OnConnected()=0;
virtual void Send(std::shared_ptr<uint8_t> buffer, int length);
void Receive();
void Disconnect();
bool connected;
protected:
virtual void OnReceived(ByteBuffer &b) = 0;
private:
void handle_Receive(const boost::system::error_code& error, std::size_t bytes_transferred );
void handle_Send(const boost::system::error_code& error, std::size_t bytes_transferred);
boost::asio::ip::tcp::socket socket_;
bool disconnecting;
boost::array<uint8_t, 1000> read_buffer_;
};
#endif
#include "Connection.h"
Connection::Connection(boost::asio::io_service& io_service)
:socket_(io_service),disconnecting(false),connected(false){}
Connection::~Connection(){}
boost::asio::ip::tcp::socket& Connection::socket(){
return socket_;
}
void Connection::Send(std::shared_ptr<uint8_t> buf, int length){
boost::asio::async_write(socket_,boost::asio::buffer(buf.get(),length),
boost::bind(&Connection::handle_Send, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
void Connection::handle_Send(const boost::system::error_code& error, std::size_t bytes_transferred){
}
void Connection::Receive(){
boost::asio::async_read(socket_,boost::asio::buffer(this->read_buffer_),
boost::bind(&Connection::handle_Receive, shared_from_this(),boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
}
void Connection::handle_Receive(const boost::system::error_code& error, std::size_t bytes_transferred)
{
if(!error)
{
if(bytes_transferred <=0){
this->Disconnect();
}else{
ByteBuffer b((std::shared_ptr)this->read_buffer_.data(), this->read_buffer_.size());
this->OnReceived(b);
this->Receive();}
}
}
void Connection::Disconnect()
{
if (!disconnecting) {
boost::system::error_code ec;
socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_send,ec);
socket_.close(ec);
disconnecting = true;
std::cout<<"disconnected"<<std::endl;
}
}
ConnectionFactory class
#pragma once
#include "Connection.h"
class ConnectionFactory
{
public:
ConnectionFactory(void);
virtual ~ConnectionFactory(void);
virtual Connection::pointer create(boost::asio::io_service& io_service) = 0;
};
#include "ConnectionFactory.h"
ConnectionFactory::ConnectionFactory(void)
{
}
ConnectionFactory::~ConnectionFactory(void)
{
}
Server Class
#ifndef _SERVER_H_
#define _SERVER_H_
#include "Connection.h"
#include "ConnectionFactory.h"
class Server
{
public:
Server(boost::asio::io_service& io_service , std::string ip,short port,boost::shared_ptr<ConnectionFactory> factory);
~Server();
private:
void start_accept();
void handle_accept(boost::shared_ptr<Connection> conn,const boost::system::error_code& error);
boost::shared_ptr<ConnectionFactory> m_factory;
boost::asio::io_service &io_service;
boost::asio::ip::tcp::acceptor acceptor_;
};
#endif
#include "Server.h"
Server::Server(boost::asio::io_service& io_service,std::string ip,short port,boost::shared_ptr<ConnectionFactory> factory)
:io_service(io_service), acceptor_(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::from_string(ip.data()), port)){
m_factory = factory;
start_accept();
std::cout<<"Socket accepting connections..."<<std::endl;
}
Server::~Server()
{
}
void Server::start_accept(){
boost::shared_ptr<Connection> conn = m_factory->create(this->io_service);
acceptor_.async_accept(conn->socket(),
boost::bind(&Server::handle_accept, this,conn,boost::asio::placeholders::error));
}
void Server::handle_accept(boost::shared_ptr<Connection> conn,const boost::system::error_code& error){
if (!error){
std::cout<<"on connected"<<std::endl;
conn->OnConnected();
conn->Receive();
start_accept();
}
//conn->Disconnect();
}
and I drevid from the static-lib and used this classes and it's working perfect
in my main.cpp
#include <iostream>
#include "auth_proto.h"
#include <Server.h>
#include <ConnectionFactory.h>
#include "AuthConnectionFactory.h"
using namespace std;
int main()
{
Auth_Setup();
try
{
boost::asio::io_service io_service;
boost::shared_ptr<ConnectionFactory> fact (new AuthConnectionFactory(io_service));
Server s(io_service,"5.113.195.156",9959,fact);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
I really don't understand what is wrong here , when it comes to the Receive() function it's receive the data from the client but it does not invoking the handle_Receive() method so I can use this data, the behavior that am waiting that it should call the handle_Receive() so I can pass the data to ByteBuffer and use it but that's not happening ......
boost::asio::async_read seems to call the read handler only when it reaches the "amount of data" passed to it.
Quoting boost's 1.46.0 reference:
async_read
Start an asynchronous operation to read a certain amount of data from a stream.
So as a solution, use socket_.async_read_some instead of boost::asio::async_read if you wish to be informed of any arbitrary amount of data received.
Another solution, as Sam Miller was trying to say in the comments, you can add a fixed size header containing the number of bytes incoming before each frame you're supposed to receive, read the header then call boost::asio::async_read with the previously extracted number.