Boost :: Asio异步UDP服务器 - 未处理的异常消息

时间:2015-05-25 17:28:21

标签: c++ multithreading sockets network-programming boost-asio

我对C ++编程相当新,来自嵌入式C的背景。我正在尝试使用Boost :: Asio将一个项目与UDP接收器组合在一起,在调试代码时,我收到一个' Unhandled exception& #39; MS Visual Studio Express 2012中的对话框。

这真的是错误还是简单的运行时反馈,因为我没有异常处理代码?

我有一个名为UDP_Listener的单例类,它在套接字成员变量上启动async_receive_from。在我的主要执行线程中,我生成另一个线程来执行io_service :: run()并创建UDP_Listener的实例。

这是创建网络对象的主要执行线程中的代码:

// UDP listener initialisation
try{
    // io_service and the work object to keep it from returning immediately
    boost::asio::io_service io_service;
    boost::asio::io_service::work work(io_service);
    // Spawn a new thread to execute the io_service run() method
    boost::thread(boost::bind(&boost::asio::io_service::run, &io_service));

    // Create the UDP listener object - singleton class
    m_pListener = new UDP_Listener(io_service);
}
catch (std::exception& e)
{
    std::cerr << e.what() << std::endl;
}

UDP_Listener类具有头文件:

#pragma once

#include "boost_1_58_0/boost/array.hpp"
#include "boost_1_58_0/boost/asio.hpp"
#include "boost_1_58_0/boost/bind.hpp"

#include "Target.h"

class UDP_Listener
{
public:
    // Constructor
    UDP_Listener(boost::asio::io_service& io_service);

    // Destructor
    ~UDP_Listener(void);

    // Start an async receive from the member socket
    void asyncReceive(void);

    // Create a list of target objects from the received byte array
    void buildTargetList(void);

private:

    void handleReceive(const boost::system::error_code& error, 
        std::size_t /*bytes_transferred*/);

    void handleSend(boost::shared_ptr<std::string> /*message*/,
      const boost::system::error_code& /*error*/,
      std::size_t /*bytes_transferred*/);

    boost::asio::ip::udp::socket m_socket;
    boost::asio::ip::udp::endpoint m_remote_endpoint;

    // Received byte array
    boost::array<signed char, 8192> m_recv_buffer;

    boost::asio::io_service& m_io_service;

    // List of target objects most recently received
    std::vector<Target> m_target_list;

    // The distance resolution (16 metres / 2^7 bits representation)
    FLOAT d_step;// = 0.125f;
    // The speed resolution (15.3 km/h / 2^7 signed bits)
    FLOAT s_step;// = 0.24f;
};

和实现(这里简化为删除不相关的函数):

#include "UDP_Listener.h"

using boost::asio::ip::udp;

/// <summary>
/// Constructor
/// </summary>
UDP_Listener::UDP_Listener(boost::asio::io_service &io_service)
    : m_io_service(io_service),
      m_socket(io_service, udp::endpoint(udp::v4(), 12345))
{
    d_step = 0.125f;
    s_step = 0.24f;

    // Start listening for UDP packets
    asyncReceive();
}

/// <summary>
/// Destructor
/// </summary>
UDP_Listener::~UDP_Listener(void)
{
    //m_io_service.stop();
    m_socket.shutdown(boost::asio::ip::udp::socket::shutdown_both);
    m_socket.close();
}

/// <summary>
/// Start listening for UDP packets
/// </summary>
void UDP_Listener::asyncReceive()
{
    m_socket.async_receive_from(
        boost::asio::buffer(m_recv_buffer), m_remote_endpoint,
        boost::bind(&UDP_Listener::handleReceive, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
}

/// <summary>
/// Handler for received packets
/// </summary>
void UDP_Listener::handleReceive(const boost::system::error_code& error,
      std::size_t /*bytes_transferred*/)
{
    if (!error || error == boost::asio::error::message_size)
    {
        if (m_recv_buffer[0] == 0x19 && m_recv_buffer[1] == 0x73)
        {   
            m_target_list.clear();
            buildTargetList();
        }
        asyncReceive();
    }
}

使用VS调试器编译和执行时,我收到以下消息: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> > at memory location 0x0674F180.

我担心我在这里做了一些根本性的错误,因为我对网络,线程管理和带操作系统的C ++缺乏经验。我不想在我的应用程序中使用本质上有缺陷的编码!

1 个答案:

答案 0 :(得分:1)

我看到的第一件事是你在异步工作之前调用ioservice在一个单独的线程上运行。这将导致run方法立即退出,并且您的异步调用将永远不会触发,因为io服务未运行。另外我会用错误代码调用ioservice运行,这样你就可以捕获这样的错误:

boost::system::error_code ec;
boost::thread(boost::bind(&boost::asio::io_service::run, &io_service, ec));
if (ec)
//do error checking here

可能发生错误的另一个地方是绑定套接字时。您使用其构造函数将套接字绑定到端口12345但是如果该端口已经绑定了套接字会发生什么?如果您没有绑定到端口的权限怎么办?传递错误代码并处理它们是一种好习惯。这是一个例子:

boost::system::error_code ec;
boost::asio::ip::address_v4 address = boost::asio::ip::address_v4::any();
boost::asio::udp::endpoint ep(address, 12345)
boost::asio::udp::socket sock(io_service);
sock.open(boost::asio::ip::udp::v4(), ec);
if (ec)
    //do error checking here
sock.bind(ep, ec);
if (ec)
    //do error checking here

//now do any reads or writes 

您获得的异常是不处理其中一个提升错误代码的结果。