构造函数失败后初始化 boost::asio 套接字

Initializing boost::asio socket after constructor failed

我创建了一个class广播UDP消息如下:

#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
#include <iostream>
#include <string>
#include <queue>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/thread.hpp>
#include <boost/thread/thread.hpp> 
#include <boost/chrono.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

using boost::asio::ip::udp;
using std::cout;
using std::cin;
using std::endl;
using std::string;
using namespace std;

template<typename T>
std::string toString(const T& value);
std::string IntToString(const int& i);

class UdpCore
{
private:
    boost::asio::ip::udp::endpoint endpoint;
    boost::asio::ip::udp::socket socket;

    string multicast_address;
    unsigned short multicast_port;
    boost::thread_group threads;    // thread group
    boost::thread* thread_main;     // main thread
    boost::thread* thread_listen;   // listen thread
    boost::thread* thread_getsend;  // get/send thread
    boost::mutex stopMutex;
    bool initialize = false;
    bool stop, showBroadcast;
    int i_getsend, i_listen, i_main, i_message, interval;
    string message;
public:
    // constructor
    UdpCore(boost::asio::io_service& io_service, std::string multicast_address, unsigned short multicast_port, int interval, bool show = false)
        : endpoint(boost::asio::ip::address::from_string(multicast_address), multicast_port),
        socket(io_service, endpoint.protocol()),
        multicast_address(multicast_address),
        multicast_port(multicast_port),
        interval(interval),
        showBroadcast(show)
    {
        Initialize(io_service, show);
    }

    ~UdpCore()
    {
        // show exit message
        cout << "Exiting UDP Core." << endl;
    }

    // initialize
    void Initialize(boost::asio::io_service& io_service, bool show = false)
    {
        if (initialize == false)
        {
            GetInfo();
        }

        boost::asio::ip::udp::endpoint endpoint(boost::asio::ip::make_address(multicast_address), multicast_port);
        boost::asio::ip::udp::socket socket(io_service, endpoint.protocol());
        socket.set_option(boost::asio::ip::udp::socket::reuse_address(true));   // no need

        thread_main = new boost::thread(boost::ref(*this));
        thread_getsend = new boost::thread(&UdpCore::Callable_GetSend, this, interval, boost::ref(i_listen), boost::ref(message));
        threads.add_thread(thread_getsend); // get/send thread
        stop = false;
        showBroadcast = show;
        i_getsend = 0;
        i_listen = 0;
        i_main = 0;
        i_message = 0;
        message.clear();

        initialize = true;
    }

    void GetInfo()
    {
        multicast_address = "192.168.0.255";
        multicast_port = 13000;
        interval = 500;
    }

    // start the threads
    void Start()
    {
        // Wait till they are finished
        threads.join_all();
    }

    // stop the threads
    void Stop()
    {
        // warning message
        cout << "Stopping all threads." << endl;

        // signal the threads to stop (thread-safe)
        stopMutex.lock();
        stop = true;
        stopMutex.unlock();

        // wait for the threads to finish
        thread_main->interrupt();   // in case not interrupted by operator()
        threads.interrupt_all();
        threads.join_all();

        // close socket after everything closes
        socket.close();
    }

    void Callable_Listen(int interval, int& count)
    {
        while (!stop)
        {
            if (message != "")
                socket.async_send_to(boost::asio::buffer(message), endpoint, [this](boost::system::error_code ec, std::size_t /*length*/)
            {
                stopMutex.lock();
                if (showBroadcast)
                {
                    cout << i_message << " - " << message << endl;  // show  count
                }
                message.clear();    //clear after sending
                stopMutex.unlock();
            });
            ++i_message;

            // wait routine
            boost::this_thread::sleep(boost::posix_time::millisec(interval));
            boost::this_thread::interruption_point();
            ++i_listen;
        }
    }

    void Callable_GetSend(int interval, int& count, string& userInput)
    {
        while (!stop)
        {
            stopMutex.lock();
            cout << "Callable_GetSend [" << count++ << "]. Enter message: ";
            getline(cin, userInput);
            if (message != "")
                socket.async_send_to(boost::asio::buffer(message), endpoint, [this](boost::system::error_code ec, std::size_t /*length*/)
            {
                if (showBroadcast)
                {
                    cout << i_message << " - " << message << endl;  // show  count
                }
                message.clear();    //clear after sending
            });
            stopMutex.unlock();

            // wait routine
            boost::this_thread::sleep(boost::posix_time::millisec(interval));
            boost::this_thread::interruption_point();
            ++i_getsend;
            ++i_message;
        }
    }

    // Thread function
    void operator () ()
    {
        while (!stop)
        {
            if (message == "STOP")
            {
                try
                {
                    this->Stop();
                }
                catch (exception e)
                {
                    cout << e.what() << endl;
                }
            }

            boost::this_thread::sleep(boost::posix_time::millisec(interval));
            boost::this_thread::interruption_point();
        }
    }

    std::string make_daytime_string()
    {
        using namespace std; // For time_t, time and ctime;
        time_t now = time(0);
        std::string result = ctime(&now);
        return result.erase(result.length() - 1, 1);
    }

    std::string some_string()
    {
        std::string result;
        result = make_daytime_string();
        return result;
    }
};

int main()
{
    try
    {
        boost::asio::io_service io_service;
        UdpCore mt(io_service, "192.168.0.255", 13000, 5000, false);
        mt.Start(); 
    }
    catch (std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
    }
}

它工作正常。但是,我希望在 class 构造函数初始化后初始化套接字(以允许用户输入)。因此,我从使用 socket 改为使用 socket 指针,正如这个 post 所建议的 .修改后的代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
#include <iostream>
#include <string>
#include <queue>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/thread.hpp>
#include <boost/thread/thread.hpp> 
#include <boost/chrono.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

using boost::asio::ip::udp;
using std::cout;
using std::cin;
using std::endl;
using std::string;
using namespace std;

template<typename T>
std::string toString(const T& value);
std::string IntToString(const int& i);

class UdpCore
{
private:
    boost::asio::ip::udp::endpoint endpoint;
    boost::shared_ptr<udp::socket> socketPtr;

    string multicast_address;
    unsigned short multicast_port;
    boost::thread_group threads;    // thread group
    boost::thread* thread_main;     // main thread
    boost::thread* thread_listen;   // listen thread
    boost::thread* thread_getsend;  // get/send thread
    boost::mutex stopMutex;
    bool initialize = false;
    bool stop, showBroadcast;
    int i_getsend, i_listen, i_main, i_message, interval;
    string message;
public:
    // constructor
    UdpCore(boost::asio::io_service& io_service, std::string multicast_address, unsigned short multicast_port, int interval, bool show = false)
        : multicast_address(multicast_address),
        multicast_port(multicast_port),
        interval(interval),
        showBroadcast(show)
    {
        UdpCore(io_service, show);
    }

    UdpCore(boost::asio::io_service& io_service, bool show = false)
        : showBroadcast(show)
    {
        Initialize(io_service, show);
    }

    // destructor
    ~UdpCore()
    {
        // show exit message
        cout << "Exiting UDP Core." << endl;
    }

    // initialize
    void Initialize(boost::asio::io_service& io_service, bool show = false)
    {
        if (initialize == false)
        {
            GetInfo();
        }

        boost::asio::ip::udp::endpoint endpoint(boost::asio::ip::address::from_string(multicast_address), multicast_port);
        socketPtr = boost::make_shared<udp::socket>(boost::ref(io_service), endpoint.protocol());
        socketPtr->set_option(boost::asio::ip::udp::socket::reuse_address(true));   // no need

        thread_main = new boost::thread(boost::ref(*this));
        thread_getsend = new boost::thread(&UdpCore::Callable_GetSend, this, interval, boost::ref(i_listen), boost::ref(message));
        threads.add_thread(thread_getsend); // get/send thread
        stop = false;
        showBroadcast = show;
        i_getsend = 0;
        i_listen = 0;
        i_main = 0;
        i_message = 0;
        message.clear();

        initialize = true;
    }

    void GetInfo()
    {
        multicast_address = "192.168.0.255";
        multicast_port = 13000;
        interval = 500;
    }

    // start the threads
    void Start()
    {
        // Wait till they are finished
        threads.join_all();
    }

    // stop the threads
    void Stop()
    {
        // warning message
        cout << "Stopping all threads." << endl;

        // signal the threads to stop (thread-safe)
        stopMutex.lock();
        stop = true;
        stopMutex.unlock();

        // wait for the threads to finish
        thread_main->interrupt();   // in case not interrupted by operator()
        threads.interrupt_all();
        threads.join_all();

        // close socket after everything closes
        socketPtr->close();
    }

    void Callable_Listen(int interval, int& count)
    {
        while (!stop)
        {
            if (message != "")
                socketPtr->async_send_to(boost::asio::buffer(message), endpoint, [this](boost::system::error_code ec, std::size_t /*length*/)
            {
                stopMutex.lock();
                if (showBroadcast)
                {
                    cout << i_message << " - " << message << endl;  // show  count
                }
                message.clear();    //clear after sending
                stopMutex.unlock();
            });
            ++i_message;

            // wait routine
            boost::this_thread::sleep(boost::posix_time::millisec(interval));
            boost::this_thread::interruption_point();
            ++i_listen;
        }
    }

    void Callable_GetSend(int interval, int& count, string& userInput)
    {
        while (!stop)
        {
            stopMutex.lock();
            cout << "Callable_GetSend [" << count++ << "]. Enter message: ";
            getline(cin, userInput);
            if (message != "")
                socketPtr->async_send_to(boost::asio::buffer(message), endpoint, [this](boost::system::error_code ec, std::size_t /*length*/)
            {
                if (showBroadcast)
                {
                    cout << i_message << " - " << message << endl;  // show  count
                }
                message.clear();    //clear after sending
            });
            stopMutex.unlock();

            // wait routine
            boost::this_thread::sleep(boost::posix_time::millisec(interval));
            boost::this_thread::interruption_point();
            ++i_getsend;
            ++i_message;
        }
    }

    // Thread function
    void operator () ()
    {
        while (!stop)
        {
            if (message == "STOP")
            {
                try
                {
                    this->Stop();
                }
                catch (exception e)
                {
                    cout << e.what() << endl;
                }
            }

            boost::this_thread::sleep(boost::posix_time::millisec(interval));
            boost::this_thread::interruption_point();
        }
    }

    std::string make_daytime_string()
    {
        using namespace std; // For time_t, time and ctime;
        time_t now = time(0);
        std::string result = ctime(&now);
        return result.erase(result.length() - 1, 1);
    }

    std::string some_string()
    {
        std::string result;
        result = make_daytime_string();
        return result;
    }
};

int main()
{
    try
    {
        boost::asio::io_service io_service;
        UdpCore mt(io_service, false);
        mt.Start();
    }
    catch (std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
    }
}

我有这些替代品:

//boost::asio::ip::udp::socket socket;
boost::shared_ptr<udp::socket> socketPtr;

//boost::asio::ip::udp::socket socket(io_service, endpoint.protocol());
//socket.set_option(boost::asio::ip::udp::socket::reuse_address(true));
socketPtr = boost::make_shared<udp::socket>(boost::ref(io_service), endpoint.protocol());
socketPtr->set_option(boost::asio::ip::udp::socket::reuse_address(true));

//socket.async_send_to(boost::asio::buffer(message), endpoint, [this](boost::system::error_code ec, std::size_t /*length*/)
socketPtr->async_send_to(boost::asio::buffer(message), endpoint, [this](boost::system::error_code ec, std::size_t /*length*/)

只有一件事与修改有关:它不起作用。我一直在仔细研究代码,但找不到它不工作的原因。有人可以帮忙吗?

在第一个示例中,除了成员 endpointsocket 之外,您还在 Initialize() 函数中创建了本地 endpointsocket。后面的对象只是未使用 - 但是,成员 endpoint 已正确初始化。

另一方面,在第二个示例中,您没有正确初始化成员 endpoint。相反,您再次创建一个本地的。但是要注意,整个代码使用的端点都是成员一。

底线:删除本地对象并为成员添加正确的初始化。