【问题标题】:Boost.Asio asynchronous server. Limit to one connectionBoost.Asio 异步服务器。限制为一个连接
【发布时间】:2018-01-24 21:25:25
【问题描述】:

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

目前尚不清楚如何完成此操作,并且在连接关闭时仍然能够重新连接。

谁能提供一个简单的例子来说明如何做到这一点?

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

【问题讨论】:

标签: c++ asynchronous boost boost-asio


【解决方案1】:

在之前的连接完成之前不要接受新的连接。

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

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

【讨论】:

  • 我不认为这是我所要求的,因为每次迭代时程序都会明确关闭连接。我希望它保持打开状态,并且只有在客户端断开连接并想要再次连接时才重新连接。我仍然要感谢您,因为您的回答使我弄清楚了如何做我所要求的。我仍在评估它,我可能最终会在这里发布代码。
  • @RicardoAngeli 这只是演示,对。您可以等到连接断开。即使这样 /nice/ 确保套接字未处于打开状态(否则,您需要一个新实例来接受新连接)
  • 这里,为了把要点带回家,一个清楚地表明不需要强制关闭套接字的版本:on coliru¹。我只是通过将netcat -C 指向它来测试它-demo vid (4.6Mb)(¹ boost 版本已过时,因此它不支持run_for)。
猜你喜欢
  • 2018-03-09
  • 1970-01-01
  • 1970-01-01
  • 2015-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-20
  • 2014-11-26
相关资源
最近更新 更多