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

标签 c++ sockets boost boost-asio shared-ptr

我创建了一个广播 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";
    }
}

它工作正常。但是,我希望在类构造函数初始化后初始化套接字(以允许用户输入)。因此,我从使用套接字改为使用套接字指针,正如此 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 之外,您还创建了一个本地 endpointsocketInitialize() 函数中。后面的对象只是未使用 - 但是,成员 endpoint 已正确初始化。

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

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

关于c++ - 构造函数失败后初始化 boost::asio 套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49249328/

相关文章:

java - 安全连接Java Socket

LINUX tcpdump - UDP数据包监控时关于IPS和端口

c++ - 在 C++ 中仅使用堆栈的后果

c++ - 我应该声明方法 "const"如果它只是 "shallow const"而不是 "deep const"吗?

c++ - 我如何将 std::vector<short>& samples2 转换为 kiss_fft_scalar* 样本?

.net - 阻塞 TCP 套接字写入然后立即关闭 - 这是一个问题吗?

c++ - 如何返回可变数量的各种类型的容器?

linux - 使用 boost::iostreams::mapped_file

c++ - map 中的两个键值可以相同吗

Windows 上的 c++ MIDI 音序器和 smf 加载器库