简体   繁体   中英

Boost.Asio asynchronous server. Limit to one connection

I'm fairly new to Boost.Asio and I want to develop an asynchronous server that limits the number of active connections to one. In other words, when a connection is established, additional connections will be denied. Once that connection is closed, another one can take its spot.

It's not immediately clear how to accomplish this and still be able to re-connect if the connection gets closed.

Could someone provide a simple example of how to do this?

EDIT: How would you take the Boost.Asio Asynchronous Server example code and edit it to limit the number of connections?

Just don't accept the new connection until the previous is done.

Simplest possible program I can come up with:

#define BOOST_ASIO_HAS_CHRONO 1
#include <boost/asio.hpp>
#include <iostream>
#include <chrono>

namespace ba = boost::asio;
using ba::ip::tcp;
using boost::system::error_code;

class Server {
    ba::io_service _svc;
    tcp::acceptor _acc{_svc};
    tcp::socket _conn{_svc};

    ba::streambuf _request, _response;

  public:
    void start(unsigned short port, std::chrono::high_resolution_clock::duration time) {
        _acc.open(tcp::v4());
        _acc.bind({{}, port});
        _acc.listen(5);

        do_accept();

        _svc.run_for(time);
    }

  private:
    void do_accept() {
        if (_conn.is_open())
            _conn.close();

        _acc.async_accept(_conn, [=](error_code ec) { handle_accept(ec); });
    }

    void handle_accept(error_code ec) {
        if (!ec) std::cout << "Accepted: " << _conn.remote_endpoint() << ", " << ec << " (" << ec.message() << ")\n";
        else     std::cout << "Accepted, " << ec << " (" << ec.message() << ")\n";

        ba::async_read_until(_conn, _request, "\r\n", [=](error_code ec, size_t xfr) { handle_read(ec, xfr); });
    }

    void handle_read(error_code ec, size_t transferred) {
        std::cout << "Read request: " << transferred << " bytes, " << ec << " (" << ec.message() << ")\n";

        std::vector<char> v(std::istreambuf_iterator<char>(&_request), {});
        std::reverse_copy(begin(v), end(v), std::ostreambuf_iterator<char>(&_response));

        ba::async_write(_conn, _response, [=](error_code ec, size_t xfr) { handle_write(ec, xfr); });
    }

    void handle_write(error_code ec, size_t transferred) {
        std::cout << "Written request: " << transferred << " bytes, " << ec << " (" << ec.message() << ")\n";

        do_accept(); // ONLY HERE initiate new accept. Could be back-log pending
    }
};

using namespace std::chrono_literals;
int main() {
    Server s;

    s.start(6767, 3s); // For demo, run 3 seconds
}

Prints

./sotest & sleep .5; for w in Hello Bye; do echo -ne "$w world\!\\r\\n" | netcat localhost 6767; done
Accepted: 127.0.0.1:43764, system:0 (Success)
Read request: 15 bytes, system:0 (Success)

!\dlrow olleHWritten request: 15 bytes, system:0 (Success)
Accepted: 127.0.0.1:43766, system:0 (Success)
Read request: 13 bytes, system:0 (Success)

!\dlrow eyBWritten request: 13 bytes, system:0 (Success)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM