为什么此函数为false,来自TCP服务器会话类成员socket_.is_Open

时间:2015-12-04 02:16:52

标签: c++ c++11 tcp server boost-asio

观察

在使用C ++ 11标准替换最初在 boost 中的所有内容之后,我使用ASIO根据此server示例构建了一个演示应用程序。服务器可以显示只有在客户端连接后才调用类成员tcp_session::start(),这表明服务器接受来自客户端的连接。

然而,当客户端发送大量数据时,我没有看到handle_read收到任何内容。最后,我发现stopped()始终为真,这意味着socket_.isOpen为假。

问题:

所以我想知道我是否需要做任何事情来将socket_设置为isOpen start(),或者socket_应该自动“打开”(意味着已连接) )?或者我的理解或假设是错误的?

我正在使用VS2015并在localhost上进行测试。

可能性:

我将默认的30秒超时更改为1秒。因此,当服务器连接时,在客户端发送数据之前,服务器是否可能超时并关闭套接字?

更新

我在handle_read中得到了一些std :: cout并停止了。我现在将超时时间设为6秒,并发现: 在客户端连接后立即调用start,然后没有任何内容表明调用handle_read,但在6秒后调用stop(),然后调用handle_read

我猜测handlers配置错误。

查找

然后我发现,如果我将async_read更改为async_read_until最初由我发表评论,则handle_read将继续,因为socket_.isopen为真。

因此,结论是,async_read无法调用handle_read,但是async_read_until可以,这变为another question。在超时停止会话之前socket_.is_open()为真。

以下是一些相关代码:

class tcp_session : public subscriber, public  std::enable_shared_from_this<tcp_session> {
public:
void start() {
    std::cout<<"started"<<std::endl;
    channel_.join(shared_from_this());
    start_read();
    input_deadline_.async_wait(
        std::bind(&tcp_session::check_deadline, shared_from_this(), &input_deadline_)
        );
    await_output();

    output_deadline_.async_wait(
        std::bind(&tcp_session::check_deadline, shared_from_this(), &output_deadline_)
    );
}
private:    
bool stopped() const {
    return !socket_.is_open();// weird that it is still not open
}
void start_read() {

    // Set a deadline for the read operation.
    input_deadline_.expires_from_now(timeout_); //was std::chrono::seconds(30) in example
    char a = 0x7F;
    // Start an asynchronous operation to read a 0x7F-delimited message or read all
    //asio::async_read_until(socket_, input_buffer_, a, std::bind(&TCP_Session::handle_read, shared_from_this(), std::placeholders::_1));

    asio::async_read(socket_, input_buffer_, 
            std::bind(&TCP_Session::handle_read, shared_from_this(), std::placeholders::_1));
}
void handle_read(const asio::error_code& ec) {
    if (stopped()) // it thinks it stopped and returned without processing
        return;

1 个答案:

答案 0 :(得分:2)

打开套接字不会暗示其连接状态,并且连接状态不会影响套接字的打开或关闭状态。两者之间的唯一保证是封闭的套接字没有连接。

客户流程示例:

using boost::asio::ip::tcp;
tcp::socket socket(io_service);                   // closed state -- no connection
socket.open(...);                                 // opened state -- no connection
socket.bind(...);
socket.connect(...);                              // opened state -- connection
... connection established ...
... remote peer terminates/closes connection ...  // opened state -- no connection
assert(socket.is_open()); 
socket.close();                                   // closed state -- no connection
assert(!socket.is_open());

示例服务器流程:

using boost::asio::ip::tcp; 
tcp::acceptor acceptor_(io_service);              // acceptor closed state
acceptor.open(...);                               // acceptor opened state
acceptor.bind(...);
acceptor.listen();                                // acceptor listening state

tcp::socket socket(io_service);                   // closed state -- no connection
acceptor.accept(socket);                          // opened state -- connection
... connection established ...
... remote peer terminates/closes connection ...  // opened state -- no connection
assert(socket.is_open());
socket.close();                                   // closed state -- no connection
assert(!socket.is_open());

assert(acceptor.is_open();
acceptor.close();                                 // acceptor closed state
assert(!acceptor.is_open());

在您的服务器中,socket_.is_open()正在返回false,然后在socket_.close()内的套接字上显式调用了tcp_session::stop()。要更深入地了解调用它的原因,请考虑:

  • 定义BOOST_ASIO_ENABLE_HANDLER_TRACKING以启用handler tracking。定义它时,Boost.Asio将有关异步操作和处理程序关系的信息写入标准错误流。
  • 附加调试器并在tcp_session::stop()
  • 中设置断点