7

我正在使用boost::asio服务器/客户端应用程序。服务器一次只接受一个连接。我想知道服务器验证客户端是否仍然连接的最佳方法是什么。

这样做的目的是我希望能够知道客户端是否崩溃,以便我可以重新开始监听新的连接尝试。

4

2 回答 2

6

在我的应用程序中,我使用了以下标志,当客户端断开连接时,我的读取就会出现。如果它在您的应用程序中,请尝试一下。连接后立即应用此标志。

在我的情况下skt_TCP是类型boost::asio::ip::tcp::socket

int32_t accept_server_socket = skt_TCP.native_handle();

int32_t timeout = 8;
int32_t cnt = 2;
int32_t intverval = 2;

// Added Keepalive flag
boost::asio::socket_base::keep_alive opt_keep_alive(true);
skt_TCP.set_option(opt_keep_alive);
setsockopt(accept_server_socket, SOL_TCP, TCP_KEEPIDLE, &timeout, sizeof(timeout));
setsockopt(accept_server_socket, SOL_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt));
setsockopt(accept_server_socket, SOL_TCP, TCP_KEEPINTVL, &intverval, sizeof(intverval));
于 2013-06-01T12:15:35.903 回答
1

这实际上取决于您选择的协议。

简单命令协议

如果您的服务器协议总是等待来自客户端的消息,那么您将始终等待async_read每个连接的客户端。当客户端以任何方式断开连接时,这应该返回错误 (EOF)。

Keep-alive 是如上所述的一种方法,但async_read为此目的 pending 的工作就很好。

简单事件协议

一个简单的事件协议涉及一个客户端监听数据和发送它的服务器。在这个协议中,服务器不知道客户端是否在那里,因为客户端只是接受数据并继续等待。客户端永远不会向服务器发送任何消息。

这就提出了keep-alive的要求。async_write操作不会以与async_read客户端已断开连接时相同的方式失败。

还有其他选项,例如让服务器始终有一个async_read尝试读取 1 个字节的挂起操作。当客户端像上面讨论的简单命令协议那样断开连接时,这将失败,但也永远不会成功,因为客户端不通过简单事件协议发送数据。

于 2015-09-10T17:15:10.080 回答