Boost.Asio异步服务器。限制为一个连接

时间:2018-01-24 21:25:25

标签: c++ asynchronous boost boost-asio

我是Boost.Asio的新手,我想开发一个异步服务器,将活动连接的数量限制为一个。换句话说,当建立连接时,将拒绝其他连接。一旦该连接关闭,另一个连接就可以占据其位置。

目前还不清楚如何完成此操作,并且如果连接关闭,仍然可以重新连接。

有人可以提供一个如何做到这一点的简单示例吗?

编辑:您将如何使用Boost.Asio异步服务器example code并对其进行编辑以限制连接数?

1 个答案:

答案 0 :(得分:0)

在上一次完成之前,不接受新连接。

我能想出的最简单的程序:

#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
}

打印

./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)