简体   繁体   English

boost :: asio tcp服务器断开连接问题

[英]boost::asio tcp server disconnect issue

I am currently writing a TCP server using boost::asio TCP socket. 我目前正在使用boost :: asio TCP套接字编写一个TCP服务器。 I've used the examples provided to make the server be statefull by wrapping the socket object in my own session object. 我使用了提供的示例,通过将套接字对象包装在我自己的会话对象中,使服务器变为全状态。

Everything works fine except for the disconnect. 除断开连接外,一切正常。 In my setup I always have a async_read_some call for each opened socket. 在我的设置中,我总是为每个打开的套接字调用async_read_some
Normal behavior is when I connect a client and disconnect it. 正常行为是当我连接客户端并断开连接时。 The data read handler is called with the error being set so I know that I have a socket disconnected. 调用数据读取处理程序并设置了错误,因此我知道套接字已断开连接。
The bad behavior is when I connect 2 clients in one order and close them in the same order. 不良行为是当我以一个顺序连接2个客户端并以相同顺序关闭它们时。 When I close the first client I get no handler being called but when I close the second one I get also the call for the first client, both to notify the disconnect. 当我关闭第一个客户端时,没有任何处理程序被调用,但是当我关闭第二个客户端时,我也获得了第一个客户端的调用,两者均通知断开连接。
Except for this issue everything seems to be working nicely. 除此问题外,其他所有功能似乎都运行良好。 Send and receive of data on multiple clients is working fine. 在多个客户端上发送和接收数据工作正常。

Anyone had this issue ? 有人遇到过这个问题吗? What could be the cause for this ? 这可能是什么原因?

bool TCPNetworkListener::StartListener()
{
    //check if already started
    if (m_SocketAcceptor.is_open())
    {
        return false;
    }

    //create the socket acceptor
    m_SocketAcceptor.open(m_TCPEndpoint.protocol());
    m_SocketAcceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
    m_SocketAcceptor.bind(m_TCPEndpoint);
    m_SocketAcceptor.listen();

    //accept async connections
    m_lastConnectedClientId++;
    TCPNetworkSession::SharedPtr new_session(new TCPNetworkSession(m_IOService, this, m_lastConnectedClientId));
    m_SocketAcceptor.async_accept(new_session->GetSocket(),
                                    boost::bind(&TCPNetworkListener::HandleNewConnection, this, new_session,
                                    boost::asio::placeholders::error));

    //all fine
    m_listenerState = NetworkListener::NLState_Running;
    return true;
}

void TCPNetworkListener::HandleNewConnection( TCPNetworkSession::SharedPtr session, const boost::system::error_code& error )
{
    if (error)
    {
        return;
    }

    session->StartNewSession();

    //accept new async connections
    m_lastConnectedClientId++;
    TCPNetworkSession::SharedPtr new_session(new TCPNetworkSession(m_IOService, this, m_lastConnectedClientId));
    m_SocketAcceptor.async_accept(new_session->GetSocket(),
        boost::bind(&TCPNetworkListener::HandleNewConnection, this, new_session,
        boost::asio::placeholders::error));
}

The session looks like this: 该会话如下所示:

TCPNetworkSession::TCPNetworkSession( boost::asio::io_service& io_service , TCPNetworkListener* handler, long clientId) :
    m_socket(io_service),
    m_IOService(io_service),
    m_networkHandler(handler),
    m_clientId(clientId),
    m_sendingData(false)
{
}

tcp::socket& TCPNetworkSession::GetSocket()
{
    return m_socket;
}

void TCPNetworkSession::StartNewSession()
{
    //notify of new connection established
    if (m_networkHandler)
    {
        m_networkHandler->ClientConnected(shared_from_this());
    }

    m_socket.set_option(boost::asio::socket_base::keep_alive(true));

    //try to read the first message data
    m_socket.async_read_some(
        boost::asio::buffer(m_readBuffer, SOCKETBUFFERLENGTH),
        boost::bind(&TCPNetworkSession::HandleReadData, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}

void TCPNetworkSession::HandleReadData( const boost::system::error_code& error, std::size_t bytes_transferred )
{
    if (error)
    {
        //we have got disconnected
        if (m_networkHandler)
        {
            m_networkHandler->ClientDisconnected(shared_from_this());
        }

        return;
    }

    //we received new data
    if (m_networkHandler)
    {
        m_readBuffer[bytes_transferred] = 0;
        std::string strData(reinterpret_cast<const char*>(m_readBuffer), bytes_transferred);
        m_networkHandler->ClientDataReceived(shared_from_this(), strData);
    }

    //try to read the next message data
    m_socket.async_read_some(
        boost::asio::buffer(m_readBuffer, SOCKETBUFFERLENGTH),
        boost::bind(&TCPNetworkSession::HandleReadData, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}

The problem was in putty. 问题出在腻子上。 I was using it for testing the server using telnet and duplicating the sessions as needed. 我使用它来使用telnet测试服务器并根据需要复制会话。 There seems to be a bug in putty that causes the socket not to get closed when you close the windows for a session. 腻子中似乎有一个错误,当您关闭会话窗口时,该错误会导致套接字无法关闭。 The sockets are all closed only when the last session of putty is closed. 仅当最后一次腻子会话关闭时,套接字才会关闭。

Thank you all for the help provided 谢谢大家提供的帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM