在Boost ASIO TCP套接字上接受多个连接

时间:2019-01-11 10:25:42

标签: c++ c++14 boost-asio

我想在一个插座上接受两次

也就是说,我监听一个端口(未连接的套接字),并希望最后获得两个连接的套接字。

换句话说,如果我在同一个tcp套接字上接受两次,则无法解决在asio中如何区分两个连接的套接字的问题。这是在Linux上。

我有一个相对简单的tcp服务器类。它假定所有可能连接到它的客户端都是同构的:如果消息正在等待发送到客户端,而没有连接,则可以将其发送到下一个连接的客户端。这对于一个连接的套接字非常有用,但是现在我需要监听多个套接字(也就是说,两个客户端将连接)。同质性假设仍然几乎是正确的,但是现在我有了另一个约束,即如果消息是对某人的响应,则该消息应该发给该人。 (回复通常是确认。)

我从倾听和接受开始:

short port = kSomethingKnown;
boost::asio::io_service& io_service_;
boost::asio::ip::tcp::socket socket_(io_service_);
boost::asio::ip::tcp::acceptor acceptor_(
    io_service_,
    boost::asio::ip::tcp::endpoint(tcp::v4(), port));

acceptor_.async_accept(socket_, [this](boost::system::error_code ec) {
    if (ec) {
        // Failed to accept.  Schedule to try again (not shown).
        return;
    }
    // Accepted.
    SendMessage();   // Flush any old messages, appropriate with a single client.
    ReceiveHeader();
});

与BSD套接字接口的比较

我将在下面解释其余部分,但这说明了要点。 ACCEPT(2)看起来像这样:

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

返回值(如果非零)是所连接套接字的文件描述符。也就是说,如果我在主机H上并且正在侦听端口P,那么sockfd代表未连接的套接字,

(H, P, tcp, 0, 0)

返回的文件描述符表示已连接的套接字,

(H, P, tcp, H1, P1)

其中H1是客户端主机,而P1是客户端的(可能是短暂的)端口,它是此套接字的另一侧。如果我第二次成功接受,我将获得另一个已连接的套接字,

(H, P, tcp, H2, P2)

其中H2和P2中的至少一个不同于H1和P1。我在asio中看不到如何引用这两个连接的套接字。我一直在阅读源代码,这在教会我很多有关asio的工作原理,而不是async_accept的工作原理。

辅助信息

首先,这是发送和接收呼叫的详细信息,但是我认为以上正是我真正需要的。了解这一点后,我将使用这些连接的套接字而不是socket_

SendMessage()以接收消息的形式存在(只是将消息推送到双端队列),而上面的形式则用于处理队列。第二种形式如下:

void SendMessage() {
    if (WeAreDead()) {
        // This checked that the connection seems valid,
        // we aren't being asked to shut down, etc.
        return;
    }
    if (send_queue_.empty()) {
        // Nothing to send.
        return;
    }
    boost::asio::async_write(
        socket_, boost::asio::buffer(send_queue_.front()),
        [this](boost::system::error_code ec, size_t length) {
            if (ec) {
                // Failed, schedule another attempt, not shown here.
                return;
            }
            send_queue_.pop_front();
            if (!send_queue_.empty()) {
                SendMessage();
            }
        });
}

ReceiveHeader()(和相似的ReceiveBody())看起来很相似,关键是这样的呼叫:

boost::asio::async_read(
    socket_, boost::asio::buffer(receive_buffer_, kTcpHeaderSize),
    boost::asio::transfer_exactly(kTcpHeaderSize),
    [this](boost::system::error_code ec, std::size_t received_length) {

同样,我发现令人困惑的部分与async_accept()有关。

1 个答案:

答案 0 :(得分:2)

您可以这样做:

    acceptor_.async_accept(
    [this] (std::error_code ec, tcp::socket&& new_socket) {

在这种情况下,您将获得一个new_socket对象,该对象表示接受的连接。我是从example那里摘下来的。

希望我能正确理解您的问题。