TCP echo server with boost asio - boost

I am trying to make tcp echo server with boost asio.
I successed transport of string data to server from client.
But I can't transport received data from client to client.
I do not know if this problem is caused by async_write() function in server code or async_read() function in client code.
I suppose that this problem is caused by thread's declaration and their function call but, I'm not sure.
Summary : I don't know correct cause of this problem..
Help me please...
sever code
#include <iostream>
#include <boost/asio.hpp>
#include <cstring>
#include <cstdlib>
#include <memory>
#include <deque>
#include <list>
#include <set>
using boost::asio::ip::tcp;
typedef std::string echo_message;
class echo_session
: public std::enable_shared_from_this<echo_session>
{
public:
echo_session(tcp::socket socket, std::set<std::shared_ptr<echo_session>>& session_place)
: socket_(std::move(socket)),
session_place_(session_place)
{
std::cout << "Session Initializing...\n";
read_msg_ = "Server!";
}
void start()
{
int se_num=0;
std::cout << "Session starting...\n";
session_place_.insert(shared_from_this());
for(auto session: session_place_)
{
se_num++;
}
std::cout << "Session num: " << se_num << std::endl;
do_read_message();
}
void deliver(const echo_message& msg)
{
this->write_msg_ = msg;
do_write();
}
private:
void do_read_message()
{
auto self(shared_from_this());
char *read_buffer = new char[128];
std::cout << "Reading Message...\n";
boost::asio::async_read(socket_,
boost::asio::buffer(read_buffer, 128),
[this, self, read_buffer](boost::system::error_code ec, std::size_t)
{
if(!ec)
{
read_msg_ = read_buffer;
std::cout << "do_read_message() Message:" << read_msg_ << std::endl;
/*
/////////////////////////////
Used Debugging Part
////////////////////////////
std::cout << "Async Read! : ";
std::cout << read_msg_ << std::endl;
std::cout << "Length:" << read_msg_.length() << std::endl;
*/
deliver(read_msg_);
do_read_message();
}
else
{
std::cout << "Async Read Failed!\n";
std::cerr << "Error: " << ec.message() << std::endl;
}
});
std::cout << "do_read_message() is returned!\n";
}
void do_write()
{
auto self(shared_from_this());
char *read_buffer = new char[sizeof(write_msg_.c_str())];
memcpy(read_buffer, write_msg_.c_str(), sizeof(write_msg_.c_str()));
boost::asio::async_write(socket_,
boost::asio::buffer(read_buffer, sizeof(read_buffer)),
[this, self, read_buffer](boost::system::error_code ec, std::size_t)
{
if(!ec)
{
std::cout << "Message <" << read_buffer << ">Writed!\n";
this->write_msg_ = "\0";
}
else
{
std::cout << "Write Failed\n";
}
std::cout << "do_write lambda returned!\n";
});
}
tcp::socket socket_;
echo_message read_msg_;
echo_message write_msg_;
std::set<std::shared_ptr<echo_session>>& session_place_;
};
class echo_server {
public:
echo_server(boost::asio::io_context& io_context,
const tcp::endpoint& endpoint)
: acceptor_(io_context, endpoint)
{
do_accept();
}
private:
void do_accept()
{
acceptor_.async_accept(
[this](boost::system::error_code ec, tcp::socket socket)
{
if(!ec)
{
std::make_shared<echo_session>(std::move(socket), sessions_)->start();
std::cout << "Accept!\n";
}
else
{
std::cout << "Accept Failed!\n";
}
do_accept();
});
}
tcp::acceptor acceptor_;
std::set<std::shared_ptr<echo_session>> sessions_;
};
int main(int args, char *argv[])
{
try
{
if( args != 2)
{
std::cerr << "Usage: server <port>" << std::endl;
return 1;
}
boost::asio::io_context io_context;
tcp::endpoint endpoint(tcp::v4(), std::atoi(argv[1]));
echo_server ex_server(io_context, endpoint);
io_context.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << std::endl;
}
return 0;
}
client code
#include <iostream>
#include <deque>
#include <thread>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
typedef std::string echo_message;
class echo_client {
public:
echo_client(boost::asio::io_context& io_context,
const tcp::resolver::results_type& endpoints)
: io_context_(io_context),
socket_(io_context)
{
do_connect(endpoints);
}
void write(const std::string string)
{
boost::asio::post(io_context_,
[this, string]()
{
//std::cout << "Post Success!\n";
do_write(string);
});
}
void close()
{
boost::asio::post(io_context_,
[this]()
{
std::cout << "Close Success!\n";
socket_.close();
});
}
private:
void do_connect(const tcp::resolver::results_type& endpoints)
{
boost::asio::async_connect(socket_, endpoints,
[this](boost::system::error_code ec, tcp::endpoint)
{
if(!ec)
{
std::cout << "Async_connect Success!\n";
do_read_message();
}
else
{
std::cout << "Async_connect error!\n";
}
});
}
void do_read_message()
{
std::cout << "read_message()" << std::endl;
//auto self(shared_from_this());
char *read_buffer = new char[128];
boost::asio::async_read(socket_,
boost::asio::buffer(read_buffer, 128),
[this, read_buffer/*, self*/](boost::system::error_code ec, std::size_t size)
{
if(!ec)
{
std::cout << "Async Read Success!\n";
read_msg_ = read_buffer;
if(read_msg_.length() != 0)
{
std::cout << "Message:" << read_msg_ << std::endl;
std::cout << "Length: " << read_msg_.length() << std::endl;
read_msg_ = "\0";
}
do_read_message();
}
else
{
std::cout << "Async_read error!\n";
std::cerr << "Error:" << ec.message() << std::endl;
socket_.close();
}
});
std::cout << "do_read_message() is returned!\n";
}
void do_write(const std::string string)
{
write_msg_ = string;
char *str = new char[sizeof(string.c_str())];
memcpy(str,string.c_str(),sizeof(string.c_str()));
boost::asio::async_write(socket_,
boost::asio::buffer(str, 128),
[this](boost::system::error_code ec, std::size_t)
{
if(!ec)
{
std::cout << "Transport Success!" << std::endl;
}
});
}
private:
boost::asio::io_context& io_context_;
tcp::socket socket_;
echo_message read_msg_;
echo_message write_msg_;
};
int main(int argc, char *argv[])
{
try
{
if(argc != 3)
{
std::cerr << "Usage: client <host> <port>" << std::endl;
return 1;
}
boost::asio::io_context io_context;
tcp::resolver resolver(io_context);
auto endpoints = resolver.resolve(argv[1], argv[2]);
echo_client c(io_context, endpoints);
std::thread t(
[&io_context]()
{
io_context.run();
});
std::string line;
while(std::cin >> line)
{
echo_message msg;
msg = line;
c.write(msg);
}
c.close();
t.join();
}
catch(std::exception e)
{
std::cerr << "Exception: " << e.what() << std::endl;
}
return 0;
}

Related

What does "boost::wrapexcept<boost::system::system_error> : body limit exceeded" mean?

I'm trying to download this link using an C++ apllication. But the it encountered exception:
terminate called after throwing an instance of 'boost::wrapexcept'
what(): body limit exceeded
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
I found out the problem is in http::write.
What on earth is going wrong? Does that mean I was just trying to download the whole file into the memory? If yes, can I continue using ssl::stream anymore? Or there's any alternative?
#ifndef __kernel_entry
#define __kernel_entry
#endif
#include <boost/asio.hpp>
#include <windows.h>
#include <boost/asio/ssl.hpp>
#include <boost/beast.hpp>
#include <boost/beast/http.hpp>
#include <boost/process.hpp>
#include <boost/process/async.hpp>
#include <iomanip>
#include <iostream>
void handle_batch(std::vector<size_t> params) {
std::mutex s_mx;
if (!params.empty()) {
// emulate some work, because I'm lazy
auto sum = std::accumulate(begin(params), end(params), 0ull);
// then wait some 100..200ms
{
using namespace std::chrono_literals;
std::mt19937 prng(std::random_device{}());
std::this_thread::sleep_for(
std::uniform_real_distribution<>(100,200)(prng)*1ms);
}
// simple thread id (thread::id displays ugly)
auto tid = std::hash<std::thread::id>{}(std::this_thread::get_id()) % 100;
// report results to stdout
std::lock_guard lk(s_mx); // make sure the output doesn't intermix
std::cout
<< "Thread #" << std::setw(2) << std::setfill('0') << tid
<< " Batch n:" << params.size()
<< "\tRange [" << params.front() << ".." << params.back() << "]"
<< "\tSum:" << sum
<< std::endl;
}
}
namespace net = boost::asio;
namespace ssl = net::ssl;
namespace beast = boost::beast;
namespace http = beast::http;
namespace process = boost::process;
using boost::system::error_code;
using boost::system::system_error;
using net::ip::tcp;
using stream = ssl::stream<tcp::socket>;
auto ssl_context() {
ssl::context ctx{ssl::context::sslv23};
return ctx;
}
void connect_https(stream& s, std::string const& host, tcp::resolver::iterator eps) {
net::connect(s.lowest_layer(), eps);
s.lowest_layer().set_option(tcp::no_delay(true));//dealt here
if (!SSL_set_tlsext_host_name(s.native_handle(), host.c_str())) {
throw system_error{ { (int)::ERR_get_error(), net::error::get_ssl_category() } };
}
s.handshake(stream::handshake_type::client);
}
auto get_request(std::string const& host, std::string const& path) {
using namespace http;
using std::cerr;
request<string_body> req;
req.version(11);cerr<<"__ver";
req.method(verb::get);cerr<<"__met";
req.target("https://" + host + path);cerr<<"__tar";
//req.set(field::user_agent, "test");
req.set(field::host, host);cerr<<"__set";
std::cerr << req << std::endl;
Sleep(1000);
return req;
}
int main() {
net::io_context io; // main thread does all io
net::thread_pool pool(6); // worker threads
// outside for lifetime
http::response_parser<http::buffer_body> response_reader;
beast::flat_buffer lookahead; // for the response_reader
std::array<char,512> buf{0}; // for download content
auto ctx = ssl_context();
ssl::stream<tcp::socket> s(io, ctx);
{ // synchronously write request
std::string host = "www.sfml-dev.org";
try{
connect_https(s, host, tcp::resolver{io}.resolve(host, "https"));
}catch(std::exception& e){std::cerr<<e.what()<<std::endl;}
http::write(s, get_request(host, "/files/SFML-2.5.1-windows-gcc-7.3.0-mingw-32-bit.zip"));
http::read_header(s, lookahead, response_reader);
std::cerr << "Headers: " << response_reader.get().base() << std::endl;
}//https://www.sfml-dev.org/files/SFML-2.5.1-windows-gcc-7.3.0-mingw-32-bit.zip
// now, asynchoronusly read contents
process::async_pipe pipe_to_zcat(io);
std::function<void(error_code, size_t)> receive_zip;
receive_zip = [&s, &response_reader, &pipe_to_zcat, &buf, &lookahead, &receive_zip](error_code ec, size_t /*ignore_this*/) {
auto& res = response_reader.get();
auto& body = res.body();
if (body.data) {
auto n = sizeof(buf) - body.size;
net::write(pipe_to_zcat, net::buffer(buf, n));
}
bool done = ec && !(ec == http::error::need_buffer);
done += response_reader.is_done();
if (done) {
std::cerr << "receive_zip: " << ec.message() << std::endl;
pipe_to_zcat.close();
} else {
body.data = buf.data();
body.size = buf.size();
http::async_read(s, lookahead, response_reader, receive_zip);
}
};
// kick off receive loop
receive_zip(error_code{}, 0);
process::async_pipe zcat_output(io);
process::child zcat(
process::search_path("zcat"),
process::std_in < pipe_to_zcat,
process::std_out > zcat_output,
process::on_exit([](int exitcode, std::error_code ec) {
std::cerr << "Child process exited with " << exitcode << " (" << ec.message() << ")\n";
}), io);
std::function<void(error_code, size_t)> receive_primes;
net::streambuf sb;
receive_primes = [&zcat_output, &sb, &receive_primes, &pool](error_code ec, size_t /*transferred*/) {
{
std::istream is(&sb);
size_t n = std::count(net::buffers_begin(sb.data()), net::buffers_end(sb.data()), '\n');
std::vector<size_t> batch(n);
std::copy_n(std::istream_iterator<size_t>(is), n, batch.begin());
is.ignore(1, '\n'); // we know a newline is pending, eat it to keep invariant
post(pool, std::bind(handle_batch, std::move(batch)));
}
if (ec) {
std::cerr << "receive_primes: " << ec.message() << std::endl;
zcat_output.close();
} else {
net::async_read_until(zcat_output, sb, "\n", receive_primes);
}
};
// kick off handler loop as well:
receive_primes(error_code{}, 0);
io.run();
pool.join();
}

boost socket example stuck in while loop

I am trying to learn boost asio socket. there is one interesting example in boost web page which set a deadline time to monitor the timeout and change async io to sync io fashion. but when I remove the deadline timer the program stuck in while loop in write_line, I don't understand why the connection can be setup but the socket write is stuck. it seems that the writing never finished ,the handler never called so the "ec" never changed. Thank you in advance!!
#include <boost/asio/connect.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/read_until.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/system/system_error.hpp>
#include <boost/asio/write.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
using boost::asio::deadline_timer;
using boost::asio::ip::tcp;
class client
{
public:
client()
: socket_(io_service_),
deadline_(io_service_)
{
deadline_.expires_from_now(boost::posix_time::seconds(10));
check_deadline(); // without this line which means without the this timer
//async_wait, the code stuck in write_line io_service_.run_one() loop .
}
void connect_handler(const boost::system::error_code& error,boost::system::error_code *er)
{
std::cerr<<"connect handler"<<std::endl;
*er = error;
std::cerr<<error<<std::endl;
}
void connect(const std::string& host, const std::string& service)
{
tcp::resolver::query query(host, service);
tcp::resolver::iterator iter = tcp::resolver(io_service_).resolve(query);
std::cerr<<"connect start"<<std::endl;
boost::system::error_code ec = boost::asio::error::would_block;
boost::asio::async_connect(socket_, iter, bind(&client::connect_handler,this,_1,&ec));
do
{io_service_.run_one();
}while (ec == boost::asio::error::would_block);
std::cerr<<"connect done"<<std::endl; // always works fine!
if (ec || !socket_.is_open())
throw boost::system::system_error(
ec ? ec : boost::asio::error::operation_aborted);
}
void write_handler(const boost::system::error_code& error, std::size_t size,boost::system::error_code* er )
{
std::cerr<<"write handler "<<std::endl;
*er=error;
std::cerr<<error<<std::endl;
}
void write_line(const std::string& line)
{
std::cerr<<"write start"<<std::endl;
std::string data = line + "\n";
boost::system::error_code ec = boost::asio::error::would_block;
boost::asio::async_write(socket_, boost::asio::buffer(data), bind(&client::write_handler,this,_1,_2,&ec));
do
{
io_service_.run_one(); //stuck here without "check_deadline();" in constructor.
}while (ec == boost::asio::error::would_block);
std::cerr<<"write done";
if (ec)
throw boost::system::system_error(ec);
}
private:
void check_deadline()
{
if (deadline_.expires_at() <= deadline_timer::traits_type::now())
{
boost::system::error_code ignored_ec;
socket_.close(ignored_ec);
deadline_.expires_at(boost::posix_time::pos_infin);
throw boost::system::system_error(ignored_ec);
}
deadline_.async_wait(std::bind(&client::check_deadline, this));
}
boost::asio::io_service io_service_;
tcp::socket socket_;
deadline_timer deadline_;
};
int main()
{
try
{
client c,d;
c.connect("216.58.194.164", "80");// google IP.
c.write_line("test");
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
Without comment out line "check_deadline();" in constructor the output is :
connect start
connect handler
system:0
connect done
write start
write handler
system:0
write done
when the line "check_deadline();" comment out in constructor, the output is :
connect start
connect handler
system:0
connect done
write start
and stuck there forever.
The whole point of that particular example is to have timeouts on blocking operations. This is why they use the async_* flavour of functions.
If you don't need that, don't use the async_* flavour at all:
#include <boost/asio.hpp>
#include <iostream>
#include <string>
using boost::asio::ip::tcp;
class client {
public:
client() : socket_(io_service_) { }
void connect(const std::string &host, const std::string &service) {
tcp::resolver::query query(host, service);
socket_.close();
boost::asio::connect(socket_, tcp::resolver(io_service_).resolve(query));
}
std::string read_line() {
boost::system::error_code ec;
boost::asio::read_until(socket_, input_buffer_, '\n', ec);
if (ec == boost::asio::error::eof)
socket_.close();
else if (ec)
throw boost::system::system_error(ec);
std::string line;
std::getline(std::istream(&input_buffer_), line);
return line;
}
void write_line(const std::string &line) {
std::string data = line + "\n";
boost::asio::write(socket_, boost::asio::buffer(data));
}
private:
boost::asio::io_service io_service_;
tcp::socket socket_;
boost::asio::streambuf input_buffer_;
};
int main(int argc, char *argv[]) {
try {
if (argc != 4) {
std::cerr << "Usage: blocking_tcp <host> <port> <message>\n";
return 1;
}
client c;
c.connect(argv[1], argv[2]);
boost::posix_time::ptime time_sent = boost::posix_time::microsec_clock::universal_time();
c.write_line(argv[3]);
for (;;) {
std::string line = c.read_line();
std::cout << "Received '" << line << "'\n";
if (line == argv[3])
break;
}
boost::posix_time::ptime time_received = boost::posix_time::microsec_clock::universal_time();
std::cout << "Round trip time: ";
std::cout << (time_received - time_sent).total_microseconds();
std::cout << " microseconds\n";
} catch (std::exception &e) {
std::cerr << "Exception: " << e.what() << "\n";
}
}
That's a lot simpler. In fact, it's too simple in case the packets arriving contain more than 1 line at a time.
Instead of "fixing" the sample by re-complicating it, it can be ENORMOUSLY simpler:
#include <boost/asio.hpp>
#include <iostream>
#include <string>
using boost::asio::ip::tcp;
int main(int argc, char *argv[]) {
try {
if (argc != 4) {
std::cerr << "Usage: blocking_tcp <host> <port> <message>\n";
return 1;
}
tcp::iostream c(argv[1], argv[2]);
boost::posix_time::ptime time_sent = boost::posix_time::microsec_clock::universal_time();
c << argv[3] << "\n";
std::string line;
while (getline(c, line)) {
std::cout << "Received '" << line << "'\n";
if (line == argv[3])
break;
}
boost::posix_time::ptime time_received = boost::posix_time::microsec_clock::universal_time();
std::cout << "Round trip time: ";
std::cout << (time_received - time_sent).total_microseconds();
std::cout << " microseconds\n";
} catch (std::exception &e) {
std::cerr << "Exception: " << e.what() << "\n";
}
}

How to get error object? when use member function in deadline_timer

I use boost::asio::deadline_timer using a member function as a handler (callback function).
If I cancel a timer, how to get error object in print() member function?
class printer
{
public:
printer(boost::asio::io_service& io)
: timer_(io, boost::posix_time::seconds(1)),
count_(0)
{
timer_.async_wait(boost::bind(&printer::print, this));
}
~printer()
{
std::cout << "Final count is " << count_ << "\n";
}
void print()
{
if (count_ < 5)
{
std::cout << count_ << "\n";
++count_;
timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
timer_.async_wait(boost::bind(&printer::print, this));
}
}
private:
boost::asio::deadline_timer timer_;
int count_;
};
int main()
{
boost::asio::io_service io;
printer p(io);
io.run();
return 0;
}
I try to set error object using bind in async_wait(), but it's compile error
timer_.async_wait(boost::bind(&printer::print, this, boost::asio::placeholders::error));
As long as your method signature matches, it should be no problem:
void print(boost::system::error_code const ec)
// and
boost::bind(&printer::print, this, boost::asio::placeholders::error)
See it Live On Coliru:
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <iostream>
class printer
{
public:
printer(boost::asio::io_service& io)
: timer_(io, boost::posix_time::seconds(1)),
count_(0)
{
timer_.async_wait(boost::bind(&printer::print, this, boost::asio::placeholders::error));
}
~printer()
{
std::cout << "Final count is " << count_ << "\n";
}
void print(boost::system::error_code const ec)
{
if (ec)
std::cout << "Error: " << ec.message() << "\n";
if (count_ < 5)
{
std::cout << count_ << "\n";
++count_;
timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
timer_.async_wait(boost::bind(&printer::print, this, boost::asio::placeholders::error));
}
}
private:
boost::asio::deadline_timer timer_;
int count_;
};
int main()
{
boost::asio::io_service io;
printer p(io);
io.run();
}

Different behavior with similar code

#include <vector>
#include <iostream>
using namespace std;
struct A
{
vector<int> v;
};
void f0(const A&& a0)
{
cout << &a0.v[0] << endl;
A a1{ move(a0.v) };
cout << &a1.v[0] << endl << endl;;
}
void f1()
{
A a0{ vector<int>(10) };
cout << &a0.v[0] << endl;
A a1{ move(a0.v) };
cout << &a1.v[0] << endl;
}
int main()
{
f0(A{ vector<int>(10) });
f1();
return 0;
}
I can't understand why in the first case addresses are different but in the second case addresses are same.

zero mq asynchronous server side is getting core dump

This is first post in the forum and need help.
I have implemented the ZeroMQ server part much same as documented here
https://github.com/egalli64/thisthread/blob/master/zmq/d2r.cpp.
Below is my code
#include <string>
#include <boost/thread.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/random.hpp>
#include "zmq2.h"
#include <pthread.h>
#include <unistd.h>
#include <cassert>
#include <string>
#include <iostream>
#include <zmq.hpp>
boost::mutex mio;
void *worker(void *arg)
{
std::cout << "in worker" << std::endl;
zmq::context_t *context = (zmq::context_t *) arg;
zmq::Socket skWorker(*context, ZMQ_DEALER);
std::cout << "in worker2" << std::endl;
skWorker.connect("inproc://backend");
std::cout<< "Worker started" << std::endl;
while(true)
{
std::cout << "in while" << std::endl;
zmq::Frames frames = skWorker.blockingRecv(2, false);
if(frames.size() == 1)
{
std::cout << "in if" << std::endl;
break;
}
// send a few replies
for(int i =0; i < 10; ++i)
{
boost::this_thread::sleep(boost::posix_time::millisec(100 * 10));
std::cout << "worker reply" << std::endl;
skWorker.send(frames);
}
}
std::cout << "terminating worker" << std::endl;
return (NULL);
}
void dumpId(const char* tag, const std::string& msg)
{
boost::lock_guard<boost::mutex> lock(mio);
std::string id = boost::lexical_cast<std::string>(boost::this_thread::get_id());
std::cout << id << ' ' << tag << ' ' << msg << std::endl;
}
int main()
{
zmq::context_t context(1);
zmq::Socket client(context, ZMQ_ROUTER);
client.bind("tcp://*:5555");
zmq::Socket workers(context, ZMQ_DEALER);
workers.bind("inproc://workers");
for (int thread_nbr = 0; thread_nbr != 2; thread_nbr++)
{
pthread_t threads;
pthread_create(&threads, NULL, worker, (void *) &context);
}
std::cout << " server started" << std::endl;
zmq_pollitem_t items [] =
{
{ client, 0, ZMQ_POLLIN, 0 },
{ workers, 0, ZMQ_POLLIN, 0 }
};
while(true)
{
if(zmq_poll(items, 2, 3000 * 1000) < 1) // 3 secs
break;
if(items[0].revents & ZMQ_POLLIN)
{
zmq::Frames frames = client.blockingRecv(2);
dumpId("Received on frontend", frames[0]);
workers.send(frames);
items[0].revents = 0; // cleanup
}
if(items[1].revents & ZMQ_POLLIN)
{
zmq::Frames frames = workers.blockingRecv(2);
dumpId("Received on backend", frames[0]);
client.send(frames);
items[1].revents = 0; // cleanup
}
}
std::cout <<"Nothing happened for a while" << std::endl;
// send a terminator to each worker
for(int i = 0; i < 2; ++i)
workers.send("");
std::cout << "Server shutdown" << std::endl;
}
After running the its getting core dumped.
Below is the output
in workerin worker server started
in worker2
in worker2
terminate called after throwing an instance of 'zmq::error_t'
terminate called recursively
Aborted (core dumped)
Could some one let me know where I m doing wrong.......
Thanks in advance....

Resources