Skip to content

Instantly share code, notes, and snippets.

@tomq42
Created March 23, 2018 08:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomq42/331b8d48110c5025e0fce93e689bd5a3 to your computer and use it in GitHub Desktop.
Save tomq42/331b8d48110c5025e0fce93e689bd5a3 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <boost/asio.hpp>
#include <thread>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/optional.hpp>
#include <time.h>
using namespace boost::asio;
using namespace boost::asio::ip;
class SimpleServer {
protected:
io_service& ioservice_;
tcp::acceptor acceptor_;
public:
SimpleServer(io_service& ioservice, const tcp::endpoint& endpoint)
: ioservice_(ioservice),
acceptor_(ioservice_)
{
acceptor_.open(endpoint.protocol());
acceptor_.set_option(tcp::acceptor::reuse_address(true));
acceptor_.bind(endpoint);
acceptor_.listen();
}
virtual ~SimpleServer() {}
virtual void start() = 0;
};
class BlockingConnection : public boost::enable_shared_from_this<BlockingConnection> {
boost::asio::strand strand_;
tcp::socket socket_;
public:
BlockingConnection(io_service& ioservice)
: strand_(ioservice), socket_(ioservice)
{}
tcp::socket& socket() {
return socket_;
}
boost::asio::strand& strand() {
return strand_;
}
void start() {
std::vector<char> b(1024);
deadline_timer timer(socket_.get_io_service());
timer.expires_from_now(boost::posix_time::milliseconds(1000));
timer.async_wait(strand_.wrap(boost::bind(&handleReadTimeout, &socket_, _1)));
socket_.read_some(buffer(b));
timer.cancel();
std::cout << "BlockingConnection terminating " << std::endl;
}
private:
static void handleReadTimeout(tcp::socket* sock, boost::system::error_code ec) {
std::cout << "timer returned : " << ec.message() << std::endl;
if (ec.value() == boost::asio::error::operation_aborted)
return;
sock->lowest_layer().cancel();
}
};
class BlockingServer : public SimpleServer {
public:
BlockingServer(io_service& ioservice, const tcp::endpoint& endpoint)
: SimpleServer(ioservice, endpoint)
{}
void start() {
boost::shared_ptr<BlockingConnection> connection(new BlockingConnection(acceptor_.get_io_service()));
acceptor_.async_accept(connection->socket(), boost::bind(&BlockingServer::handleAccept, this, connection));
}
private:
void handleAccept(boost::shared_ptr<BlockingConnection> connection) {
connection->start();
start();
}
};
tcp::endpoint getEndpoint(const char* portString) {
io_service ioservice;
tcp::resolver resolver(ioservice);
tcp::resolver::query query("localhost", portString);
return *resolver.resolve(query);
}
void runServer(int threadCount) {
io_service ioservice;
BlockingServer blockingServer(ioservice, getEndpoint("8885"));
blockingServer.start();
std::vector<std::thread> threads;
for (int i = 0; i < threadCount; i++) {
threads.push_back(std::thread(boost::bind(&io_service::run, &ioservice)));
}
for (int i = 0; i < threadCount; i++) {
threads[i].join();
}
}
int main() {
io_service ioservice;
std::thread serverThread(boost::bind(runServer, 2));
sleep(1);
tcp::socket socket(ioservice);
socket.connect(getEndpoint("8885"));
// And never send anything.
//
serverThread.join();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment