debug websocket++ broadcast_server.cpp ('owner

2019-07-15 09:59发布

问题:

Zaphoyd's broadcast_server.cpp looks like the perfect backbone for a websocket server that it can quickly accept and send messages & connections with a thread for the real action so not to interrupt the communications. https://github.com/zaphoyd/websocketpp/blob/experimental/examples/broadcast_server/broadcast_server.cpp

His simple print_server.cpp example compiles easily; however, I'm getting a few compile errors with broadcast_server.cpp.

root@server:~# g++ -O3 broadcast_server.cpp -I ~/websocketpp-experimental/ -lboost_system
broadcast_server.cpp:126:37: error: 'owner_less' is not a member of 'std'
broadcast_server.cpp:126:37: error: 'owner_less' is not a member of 'std'
broadcast_server.cpp:126:70: error: 'con_list' was not declared in this scope
broadcast_server.cpp:126:70: error: template argument 2 is invalid
broadcast_server.cpp:126:18: warning: 'typedef' was ignored in this declaration [enabled by default]
broadcast_server.cpp:129:5: error: 'con_list' does not name a type
broadcast_server.cpp: In member function 'void broadcast_server::process_messages()':
broadcast_server.cpp:109:17: error: 'm_connections' was not declared in this scope
broadcast_server.cpp:112:17: error: 'm_connections' was not declared in this scope
broadcast_server.cpp:116:17: error: 'con_list' has not been declared
broadcast_server.cpp:116:36: error: expected ';' before 'it'
broadcast_server.cpp:117:22: error: 'it' was not declared in this scope
broadcast_server.cpp:117:27: error: 'm_connections' was not declared in this scope

I'm new to c++, and these are probably simple issues, but I can't find my way through them.

'owner_less' is not a member of 'std'? http://en.cppreference.com/w/cpp/memory/owner_less

I'm guessing that the template argument 2 error will go away when the above is solved.

'con_list' was not declared in this scope when it's right there in the private:? same with 'm_connections'?

I'm guessing that 'con_list' has not been declared will go away when the above error does.

I don't know which 'it' it's talking about or why it should have a ; in front of it.

versions

Ubuntu 12.10

gcc --version gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2

boost 1.53.0

extra #includes

#include <cstdlib>
#include <iostream>
#include <memory>
#include <set>

still nothing

-std=c++11

In file included from /usr/include/c++/4.7/map:60:0,
                 from /usr/local/include/boost/date_time/gregorian/greg_month.hpp:18,
                 from /usr/local/include/boost/date_time/gregorian/greg_ymd.hpp:16,
                 from /usr/local/include/boost/date_time/gregorian/greg_calendar.hpp:16,
                 from /usr/local/include/boost/date_time/gregorian/gregorian_types.hpp:19,
                 from /usr/local/include/boost/date_time/posix_time/posix_time_config.hpp:18,
                 from /usr/local/include/boost/date_time/posix_time/posix_time_system.hpp:13,
                 from /usr/local/include/boost/date_time/posix_time/ptime.hpp:12,
                 from /usr/local/include/boost/date_time/posix_time/posix_time_types.hpp:12,
                 from /usr/local/include/boost/thread/thread_time.hpp:11,
                 from /usr/local/include/boost/thread/lock_types.hpp:18,
                 from /usr/local/include/boost/thread/pthread/thread_data.hpp:12,
                 from /usr/local/include/boost/thread/thread.hpp:17,
                 from /usr/local/include/boost/thread.hpp:13,
                 from /root/websocketpp-experimental/websocketpp/common/thread.hpp:41,
                 from /root/websocketpp-experimental/websocketpp/concurrency/basic.hpp:31,
                 from /root/websocketpp-experimental/websocketpp/config/core.hpp:35,
                 from /root/websocketpp-experimental/websocketpp/config/asio_no_tls.hpp:31,
                 from broadcast_server.cpp:1:
/usr/include/c++/4.7/bits/stl_tree.h: In instantiation of 'class std::_Rb_tree<boost::weak_ptr<void>, boost::weak_ptr<void>, std::_Identity<boost::weak_ptr<void> >, std::owner_less<boost::weak_ptr<void> >, std::allocator<boost::weak_ptr<void> > >':
/usr/include/c++/4.7/bits/stl_set.h:116:17:   required from 'class std::set<boost::weak_ptr<void>, std::owner_less<boost::weak_ptr<void> > >'
broadcast_server.cpp:132:14:   required from here
/usr/include/c++/4.7/bits/stl_tree.h:471:31: error: invalid use of incomplete type 'struct std::owner_less<boost::weak_ptr<void> >'
In file included from /usr/include/c++/4.7/bits/shared_ptr.h:52:0,
                 from /usr/include/c++/4.7/memory:87,
                 from /usr/local/include/boost/config/no_tr1/memory.hpp:21,
                 from /usr/local/include/boost/smart_ptr/shared_ptr.hpp:27,
                 from /usr/local/include/boost/shared_ptr.hpp:17,
                 from /usr/local/include/boost/date_time/time_clock.hpp:17,
                 from /usr/local/include/boost/thread/thread_time.hpp:9,
                 from /usr/local/include/boost/thread/lock_types.hpp:18,
                 from /usr/local/include/boost/thread/pthread/thread_data.hpp:12,
                 from /usr/local/include/boost/thread/thread.hpp:17,
                 from /usr/local/include/boost/thread.hpp:13,
                 from /root/websocketpp-experimental/websocketpp/common/thread.hpp:41,
                 from /root/websocketpp-experimental/websocketpp/concurrency/basic.hpp:31,
                 from /root/websocketpp-experimental/websocketpp/config/core.hpp:35,
                 from /root/websocketpp-experimental/websocketpp/config/asio_no_tls.hpp:31,
                 from broadcast_server.cpp:1:
/usr/include/c++/4.7/bits/shared_ptr_base.h:270:12: error: declaration of 'struct std::owner_less<boost::weak_ptr<void> >'

how i installed (dependencies, actual program, etc)

https://github.com/zaphoyd/websocketpp/wiki/Setup-0.3X-on-Ubuntu-12.10

alternatives welcome

If anyone has alternatives to std::owner_less, please post them.

回答1:

std::owner_less is a C++11 STL feature that allows you to put std::weak_ptr in associative containers like set and map. Ultimately, connection_hdl is a weak_ptr, and that is why it needs the custom comparison function.

WebSocket++ 0.3.x can be configured via preprocessor defines to use either C++03 + Boost or C++11. By default it uses C++03 + Boost. Boost weak_ptr works a little differently and does not need a custom comparison function. If you use a list, queue, or vector it is also unnecessary since those containers do not use the connection_hdl as keys.

Most of the examples in the 0.3.x manual and bundled with the library use C++11 because it is a lot more clean and concise. To compile and link those examples as is you will need a C++11 compiler and to use the appropriate C++11 compiler flags and WebSocket++ defines. Scons is the build system that I use to automate building & running all of the examples and unit tests. It is not necessary to build and run individual example programs. Any other build system should work fine, as will feeding compiler arguments ad hoc on the command line.

I've set up a page in the manual that describes the various options for enabling/disabling C++11 features. http://www.zaphoyd.com/websocketpp/manual/reference/cpp11-support. This manual page has a list of recommended compiler flags for the Operating systems and compilers I use most for testing.

For g++ 4.7 on Linux I would recommend: "-std=c++0x -D_WEBSOCKETPP_CPP11_STL_ -D_WEBSOCKETPP_NO_CPP11_REGEX_ -lboost_regex -lboost_system". This enables all C++11 features except the library (which is broken/buggy), and brings in the Boost version instead.



回答2:

After reading the documentation, I think you need to define BOOST_ROOT_CPP11 when building.

Similar to BOOST_ROOT but allows linking to a separate version of Boost compiled against a C++11 STL

I based this on the following header

#ifdef _WEBSOCKETPP_CPP11_MEMORY_
    using std::shared_ptr;
    using std::weak_ptr;
    using std::enable_shared_from_this;
    using std::static_pointer_cast;

    typedef std::unique_ptr<unsigned char[]> unique_ptr_uchar_array;
#else
    using boost::shared_ptr;
    using boost::weak_ptr;
    using boost::enable_shared_from_this;
    using boost::static_pointer_cast;

    typedef boost::scoped_array<unsigned char> unique_ptr_uchar_array;
#endif

Which should use std::weak_ptr instead of boost::weak_ptr


If you'd like to use an alternate container instead of std::set, modify the example similar to this pseudo code

         if (a.type == SUBSCRIBE) {
                boost::unique_lock<boost::mutex> lock(m_connection_lock);
                m_connections.push_back(a.hdl);
            } else if (a.type == UNSUBSCRIBE) {
                boost::unique_lock<boost::mutex> lock(m_connection_lock);
                m_connections.erase(std::remove(m_connections.begin(), m_connections.end(), a.hdl));
            } else if (a.type == MESSAGE) {
                boost::unique_lock<boost::mutex> lock(m_connection_lock);

                con_list::iterator it;
                for (it = m_connections.begin(); it != m_connections.end(); ++it) {
                    m_server.send(*it,a.msg);
                }
            } else {
                // undefined.
            }
        }
    }
private:
    typedef std::deque<connection_hdl> con_list;

Which will use std::deque instead of std::set. The ordering will not be used, but for what I can tell that isn't needed in this example.