套接字已接受,但m_socket.remote_endpoint引发传输端点未连接

时间:2017-08-18 02:52:38

标签: c++ boost-asio

代码:

Listener.hpp:

template <typename SocketType>
void Listener<SocketType>::BeginAccept()
{
    auto worker = SelectWorker();
    auto socket = worker->CreateSocket();

    m_acceptor->async_accept(socket->GetAsioSocket(),
        [this, worker, socket] (const boost::system::error_code &ec)
    {
        this->OnAccept(worker, socket, ec);
    });
}

template <typename SocketType>
void Listener<SocketType>::OnAccept(NetworkThread<SocketType> *worker, std::shared_ptr<SocketType> const& socket, const boost::system::error_code &ec)
{
    // an error has occurred
    if (ec)
        worker->RemoveSocket(socket.get());
    else
        socket->Open();

    BeginAccept();
}

Socket.cpp:

bool Socket::Open()
{
    try
    {
        const_cast<std::string &>(m_address) = m_socket.remote_endpoint().address().to_string();
        const_cast<std::string &>(m_remoteEndpoint) = boost::lexical_cast<std::string>(m_socket.remote_endpoint());
    }
    catch (boost::system::error_code& error)
    {
        sLog.outInfo("Socket::Open() failed to get remote address.  Error: %s", error.message().c_str());
        return false;
    }
    catch (const std::exception& error)
    {
        sLog.outInfo("Socket::Open() failed(with std::exception) to get remote address.  Error: %s", error.what());
        return false;
    }
    catch (...)
    {
        sLog.outError("Socket::Open() failed to get remote address.  Other error");
        return false;
    }

    m_outBuffer.reset(new PacketBuffer);
    m_secondaryOutBuffer.reset(new PacketBuffer);
    m_inBuffer.reset(new PacketBuffer);

    StartAsyncRead();

    return true;
}

这与TCP攻击有关吗?

编辑:gdb:

(gdb) p m_socket
$1 = {<boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >> = {<boost::asio::basic_io_object<boost::asio::stream_socket_service<boost::asio::ip::tcp>, true>> = {
      implementation = {<boost::asio::detail::reactive_socket_service_base::base_implementation_type> = {socket_ = 21, state_ = 80 'P', reactor_data_ = 0x7ffff0005120}, protocol_ = {family_ = 2}}, service_ = 0x7f2b30}, <boost::asio::socket_base> = {
      static message_peek = 2, static message_out_of_band = 1, static message_do_not_route = 4, static message_end_of_record = 128, static max_connections = 128}, <No data fields>}, <No data fields>}
(gdb) p m_socket.is_open()
$2 = true
(gdb) bt
#0  MaNGOS::Socket::Open (this=0x7ffff0003c40) at /home/ubuntu/MoltenCore/MoltenCore/src/shared/Network/Socket.cpp:52
#1  0x00000000004fbff1 in MaNGOS::Listener<AuthSocket>::OnAccept (this=0x7fffffffe6c0, worker=0x8041e0, socket=std::shared_ptr (count 2, weak 1) 0x7ffff0003c40, ec=...) at /home/ubuntu/MoltenCore/MoltenCore/src/shared/Network/Listener.hpp:121
#2  0x00000000004fa030 in MaNGOS::Listener<AuthSocket>::BeginAccept()::{lambda(boost::system::error_code const&)#1}::operator()(boost::system::error_code const&) const (__closure=0x7ffff4ec8be0, ec=...)
    at /home/ubuntu/MoltenCore/MoltenCore/src/shared/Network/Listener.hpp:110
#3  0x0000000000502a2d in boost::asio::detail::binder1<MaNGOS::Listener<AuthSocket>::BeginAccept()::{lambda(boost::system::error_code const&)#1}, boost::system::error_code>::operator()() (this=0x7ffff4ec8be0) at /usr/include/boost/asio/detail/bind_handler.hpp:47
#4  0x00000000005020c3 in boost::asio::asio_handler_invoke<boost::asio::detail::binder1<MaNGOS::Listener<AuthSocket>::BeginAccept()::{lambda(boost::system::error_code const&)#1}, boost::system::error_code> >(boost::asio::detail::binder1<MaNGOS::Listener<AuthSocket>::BeginAccept()::{lambda(boost::system::error_code const&)#1}, boost::system::error_code>&, ...) (function=...) at /usr/include/boost/asio/handler_invoke_hook.hpp:69
#5  0x00000000005014b8 in boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder1<MaNGOS::Listener<AuthSocket>::BeginAccept()::{lambda(boost::system::error_code const&)#1}, boost::system::error_code>, {lambda(boost::system::error_code const&)#1}>(boost::asio::detail::binder1<MaNGOS::Listener<AuthSocket>::BeginAccept()::{lambda(boost::system::error_code const&)#1}, boost::system::error_code>&, {lambda(boost::system::error_code const&)#1}&) (function=..., context=...)
    at /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:37
#6  0x0000000000500886 in boost::asio::detail::reactive_socket_accept_op<boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >, boost::asio::ip::tcp, MaNGOS::Listener<AuthSocket>::BeginAccept()::{lambda(boost::system::error_code const&)#1}>::do_complete(boost::asio::detail::task_io_service*, boost::asio::detail::task_io_service_operation*, boost::system::error_code const&, unsigned long) (owner=0x8084d0, base=0x804910) at /usr/include/boost/asio/detail/reactive_socket_accept_op.hpp:123
#7  0x00000000004f0300 in boost::asio::detail::task_io_service_operation::complete (this=0x804910, owner=..., ec=..., bytes_transferred=0) at /usr/include/boost/asio/detail/task_io_service_operation.hpp:38
#8  0x00000000004f1d55 in boost::asio::detail::epoll_reactor::descriptor_state::do_complete (owner=0x8084d0, base=0x804140, ec=..., bytes_transferred=1) at /usr/include/boost/asio/detail/impl/epoll_reactor.ipp:651
#9  0x00000000004f0300 in boost::asio::detail::task_io_service_operation::complete (this=0x804140, owner=..., ec=..., bytes_transferred=1) at /usr/include/boost/asio/detail/task_io_service_operation.hpp:38
#10 0x00000000004f2823 in boost::asio::detail::task_io_service::do_run_one (this=0x8084d0, lock=..., this_thread=..., ec=...) at /usr/include/boost/asio/detail/impl/task_io_service.ipp:372
#11 0x00000000004f23a1 in boost::asio::detail::task_io_service::run (this=0x8084d0, ec=...) at /usr/include/boost/asio/detail/impl/task_io_service.ipp:149
#12 0x00000000004f2abc in boost::asio::io_service::run (this=0x7ef540) at /usr/include/boost/asio/impl/io_service.ipp:59
#13 0x00000000004f7c89 in MaNGOS::Listener<AuthSocket>::Listener(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)::{lambda()#1}::operator()() const () at /home/ubuntu/MoltenCore/MoltenCore/src/shared/Network/Listener.hpp:84
#14 0x0000000000505624 in std::_Bind_simple<MaNGOS::Listener<AuthSocket>::Listener(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)::{lambda()#1} ()>::_M_invoke<>(std::_Index_tuple<>) (this=0x8049c8)
    at /usr/include/c++/5/functional:1531
#15 0x0000000000504f38 in std::_Bind_simple<MaNGOS::Listener<AuthSocket>::Listener(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)::{lambda()#1} ()>::operator()() (this=0x8049c8) at /usr/include/c++/5/functional:1520
#16 0x0000000000504416 in std::thread::_Impl<std::_Bind_simple<MaNGOS::Listener<AuthSocket>::Listener(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)::{lambda()#1} ()> >::_M_run() (this=0x8049b0) at /usr/include/c++/5/thread:115
#17 0x00007ffff6c98c80 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#18 0x00007ffff7bc16ba in start_thread (arg=0x7ffff4ec9700) at pthread_create.c:333
#19 0x00007ffff63fe82d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109

编辑: NetworkThread.hpp:

template <typename SocketType>
class NetworkThread
{
    private:
        boost::asio::io_service m_service;

        std::mutex m_socketLock;
        std::unordered_set<std::shared_ptr<SocketType>> m_sockets;

        // note that the work member *must* be declared after the service member for the work constructor to function correctly
        std::unique_ptr<boost::asio::io_service::work> m_work;

        std::thread m_serviceThread;

    public:
        NetworkThread() : m_work(new boost::asio::io_service::work(m_service))
        {
            m_serviceThread = std::thread([this] { boost::system::error_code ec; this->m_service.run(ec); });
        }

        ~NetworkThread()
        {
            // Allow io_service::run() to exit.
            m_work.reset();
            m_service.stop();
            m_serviceThread.join();

            // attempt to gracefully close any open connections
            for (auto i = m_sockets.begin(); i != m_sockets.end();)
            {
                auto const current = i;
                ++i;

                if (!(*current)->IsClosed())
                    (*current)->Close();
            }
        }

        size_t Size() const { return m_sockets.size(); }

        std::shared_ptr<SocketType> CreateSocket();

        void RemoveSocket(Socket *socket)
        {
            std::lock_guard<std::mutex> guard(m_socketLock);
            m_sockets.erase(socket->shared<SocketType>());
        }
};

template <typename SocketType>
std::shared_ptr<SocketType> NetworkThread<SocketType>::CreateSocket()
{
    std::lock_guard<std::mutex> guard(m_socketLock);

    auto const i = m_sockets.emplace(std::make_shared<SocketType>(m_service, [this] (Socket *socket) { this->RemoveSocket(socket); }));

    return *i.first;
}

1 个答案:

答案 0 :(得分:2)

问题完全不同:

在您的代码中:

template <typename SocketType>
void Listener<SocketType>::OnAccept(
    NetworkThread<SocketType> *worker, 
    std::shared_ptr<SocketType> const& socket, 
    const boost::system::error_code &ec )
{
   // at this point, socket has 1 reference count, held by the lambda 
   // in BeginAccept, its reference count cannot increase, since it's 
   // constant.  

    // ...     
    BeginAccept(); // this creates a new, distinct  instance of the lambda 
                   // fuinction object in BeginAccept.

    // when we exit, constrol is given back to calling lambda in BeginAccept
    // its destructor happily deletes the socket, since its reference count
    // is still only 1.
}

底线: OnAccept()需要按值接收套接字指针,并且需要以某种方式传输或存储此共享指针。通常这样做 通过将shared_ptr传递给BeginReceive() BY VALUE 。然后,BeginReceive()必须负责保持套接字指针处于活动状态,直到连接终止,这通常是通过将指针作为参数或作为lambda捕获传递回自身来执行此操作,始终按值。

修复代码的最简单方法是将调用移至StartAsyncRead()OnAccept(),因为那里有一个方便的套接字shared_ptr副本。