在TCP套接字上执行async_read_some()时EOF ...但是连接仍处于打开状态

时间:2019-01-18 13:56:05

标签: c++ linux boost-asio tcpclient

我正在研究处理TCP套接字连接的一段代码上的一个奇怪问题:每隔10分钟,我们的客户端在使用boost async_read_some()读取数据时会收到一个EOF错误。 当客户端<->服务器连接丢失并且因此我们的客户端正常关闭连接然后重新打开它时,通常会发生这种情况。

但是,当更深入地寻找EOF错误的原因时,我发现:

  1. 服务器未收到与客户端相同的EOF错误(它们都使用相同的代码来处理通信),但在我杀死客户端进程时成功检测到客户端断开连接。
  2. 连接实际上仍在进行:禁用重新连接代码并忽略该错误,客户端和服务器继续进行数据交换而没有问题...
  3. 按照第2点所述,不再发生EOF错误,因此似乎仅在连接10分钟后发生了一次。

有人对我为什么得到EOF有任何想法吗?我在Gentoo Linux上使用Boost v1.56.0。

先谢谢您。 SiS。

编辑:这是代码的简化版本,给了我这个问题(很抱歉,但是我无法发布实际的代码):

#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/signals2.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <cstddef>

static const unsigned int g_reconnect_time = 15; // Seconds

class conn_t
{
public:

    conn_t( std::string ip, int port, boost::asio::io_service& io_service ) :
        m_tcp_host(ip),
        m_tcp_port(port),
        m_io_service( io_service ),
        m_socket( io_service ),
        m_reconnect_interval( g_reconnect_time ),
        m_reconnect_timer( io_service, m_reconnect_interval )   
    {
    }


    ~conn_t()
    {
        disconnect();
    }   


    bool connect()
    {
        using boost::asio::ip::tcp;
        tcp::resolver resolver( m_io_service );
        tcp::resolver::query query( tcp_host, m_tcp_port);
        tcp::resolver::iterator endpoint_iterator = resolver.resolve( query );
        tcp::resolver::iterator end;
        boost::system::error_code error = boost::asio::error::host_not_found;

        while ( error && ( endpoint_iterator != end ) )
        {
            m_socket.close();
            m_socket.connect( *endpoint_iterator++, error );
        }

        if ( error ) 
        {
            // Bail out and schedule for retry:
            queue_reconnect();
            return false;
        }

        if ( !m_socket.is_open() )
            return false;

        read_data();
        return true;
    }


    void disconnect()
    {
        m_socket.close();
    }


    void read_data()
    {
        m_socket.async_read_data_some( boost::asio::buffer( m_buff ),
            [this]( const boost::system::error_code& error, std::size_t len )
            {
                if ( handle_error( error ) )
                {
                     std::cerr << "Error read_dataing data: " << std::endl;
                    reconnect();
                } 
                else 
                {
                    std::cerr << "got " << len << " bytes of data" );
                    // process data here...
                    read_data();
                }
            } );
    }


    void reconnect()
    {
        queue_reconnect();
    }


private:

    bool handle_error ( const boost::system::error_code& error )
    {
        if ( error && error != boost::asio::error::operation_aborted ) 
        {
            std::cerr << "Socket i/o error: " << error.message() << std::endl;
            boost::system::error_code ignored_ec;
            m_socket.shutdown( boost::asio::ip::tcp::socket::shutdown_both, ignored_ec );
            m_socket.close();

            return true;
        }
        return false;
    }


    void queue_reconnect()
    {
        auto new_deadline = m_reconnect_timer.expires_at() + m_reconnect_interval;

        if ( new_deadline > boost::asio::deadline_timer::traits_type::now() )
            m_reconnect_timer.expires_at( new_deadline );
        else
            m_reconnect_timer.expires_from_now( m_reconnect_interval );

        m_reconnect_timer.async_wait( boost::bind( &conn_t::start, this ) );

    }

private:

    std::string tcp_host;
    int m_tcp_port;
    boost::asio::io_service& m_io_service;
    boost::asio::ip::tcp::socket  m_socket;
    boost::posix_time::seconds m_reconnect_interval;
    boost::asio::deadline_timer m_reconnect_timer;
    char m_buff[1024];
};

0 个答案:

没有答案