【发布时间】:2019-01-11 10:25:42
【问题描述】:
我想在一个套接字上接受两次
也就是说,我监听一个端口(一个未连接的套接字),最后想得到两个连接的套接字。
换一种说法,如果我在同一个 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代表一个未连接的socket,
(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 的工作原理。
辅助细节
Fwiw,这里是发送和接收呼叫的详细信息,但我认为以上是我真正需要的。一旦我理解了这一点,我就会使用那些连接的套接字而不是 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() 有关。
【问题讨论】:
标签: c++ c++14 boost-asio