Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,8 @@ subprotocol_server = SConscript('#/examples/subprotocol_server/SConscript',varia
# telemetry_server
telemetry_server = SConscript('#/examples/telemetry_server/SConscript',variant_dir = builddir + 'telemetry_server',duplicate = 0)

# external_io_service
external_io_service = SConscript('#/examples/external_io_service/SConscript',variant_dir = builddir + 'external_io_service',duplicate = 0)
# external_io_context
external_io_context = SConscript('#/examples/external_io_context/SConscript',variant_dir = builddir + 'external_io_context',duplicate = 0)

if not env['PLATFORM'].startswith('win'):
# iostream_server
Expand Down
12 changes: 6 additions & 6 deletions docs/faq.dox
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@ Note: some browsers will allow the connection to continue if they requested a su

### How do I cleanly exit an Asio transport based program

The Asio transport based clients and servers use the Asio library's underlying `io_service` to handle asyncronous networking operations. The standard behavior of the io_service is to run until there are no async operations left and then return. WebSocket++, when using the Asio transport, behaves like a standard Asio application. If you want your WebSocket++/Asio based program to stop network operations and cleanly close all sockets you will want to do the following:
The Asio transport based clients and servers use the Asio library's underlying `io_context` to handle asyncronous networking operations. The standard behavior of the io_context is to run until there are no async operations left and then return. WebSocket++, when using the Asio transport, behaves like a standard Asio application. If you want your WebSocket++/Asio based program to stop network operations and cleanly close all sockets you will want to do the following:

- For servers, call `websocketpp::transport::asio::endpoint::stop_listening` to initiate the closing of the server listening socket.
- For clients, if you have engaged perpetual mode with `websocketpp::transport::asio::endpoint::start_perpetual`, disable it with `websocketpp::transport::asio::endpoint::stop_perpetual`.
- For both, run `websocketpp::endpoint::close` or `websocketpp::connection::close` on all currently outstanding connections. This will initiate the WebSocket closing handshake for these connections
- Wait. Asio is asyncronous. When the calls to the above methods (stop_listening, close, etc) complete the server *will still be listening*, the connections *will still be active* until the io_service gets around to asyncronously processing the socket and WebSocket protocol closing handshakes. The `io_service::run` method will exit cleanly and automatically when all operations are complete.
- Wait. Asio is asyncronous. When the calls to the above methods (stop_listening, close, etc) complete the server *will still be listening*, the connections *will still be active* until the io_context gets around to asyncronously processing the socket and WebSocket protocol closing handshakes. The `io_context::run` method will exit cleanly and automatically when all operations are complete.

__WARNING__: Asio's `io_service` has a method called `stop`. WebSocket++ wraps this method as `websocketpp::transport::asio::endpoint::stop`. While this operation has a benign sounding name, it is a powerful and destructive operation that should only be used in special cases. If you are using `io_service::stop` or `endpoint::stop` without a very good reason your program is likely broken and may exhibit erratic behavior. Specifically, `io_service::stop` stops the processing of events entirely. This does not give current operations (such as socket closing handshakes) the opportunity to finish. It will leave your sockets in a dangling state that may invoke operating system level timeouts or other errors.
__WARNING__: Asio's `io_context` has a method called `stop`. WebSocket++ wraps this method as `websocketpp::transport::asio::endpoint::stop`. While this operation has a benign sounding name, it is a powerful and destructive operation that should only be used in special cases. If you are using `io_context::stop` or `endpoint::stop` without a very good reason your program is likely broken and may exhibit erratic behavior. Specifically, `io_context::stop` stops the processing of events entirely. This does not give current operations (such as socket closing handshakes) the opportunity to finish. It will leave your sockets in a dangling state that may invoke operating system level timeouts or other errors.

__Special cases__:
- If your client uses the `start_perpetual` method it will prevent the io_service from exiting even if it has nothing to do. This is useful if you want a client endpoint to idle in the background to allow new connections to be formed on demand rather than generating a new endpoint for each.
- If you are using an external io_service and/or are placing non-WebSocket++ operations on the `io_service` those operations may keep the `io_service` open even after all WebSocket++ operations have completed.
- If you are using `poll`/`poll_one`/`run_one` or otherwise manually driving the `io_service` event loop you may need to adjust usage to make sure you are correctly recognizing the "done with work" and "not done but idling / `io_service::work`" cases.
- If your client uses the `start_perpetual` method it will prevent the io_context from exiting even if it has nothing to do. This is useful if you want a client endpoint to idle in the background to allow new connections to be formed on demand rather than generating a new endpoint for each.
- If you are using an external io_context and/or are placing non-WebSocket++ operations on the `io_context` those operations may keep the `io_context` open even after all WebSocket++ operations have completed.
- If you are using `poll`/`poll_one`/`run_one` or otherwise manually driving the `io_context` event loop you may need to adjust usage to make sure you are correctly recognizing the "done with work" and "not done but idling / `io_context::work`" cases.

### Is there a way to check the validity of a `connection_hdl`?

Expand Down
2 changes: 1 addition & 1 deletion examples/broadcast_server/broadcast_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class broadcast_server {
return;
}

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
//try {
m_server.run();
//} catch (const std::exception & e) {
Expand Down
2 changes: 1 addition & 1 deletion examples/debug_client/debug_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class perftest {

m_endpoint.connect(con);

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
m_start = std::chrono::high_resolution_clock::now();
m_endpoint.run();
}
Expand Down
2 changes: 1 addition & 1 deletion examples/debug_server/debug_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ int main() {
// Start the server accept loop
echo_server.start_accept();

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
echo_server.run();
} catch (websocketpp::exception const & e) {
std::cout << e.what() << std::endl;
Expand Down
2 changes: 1 addition & 1 deletion examples/echo_client/echo_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ int main(int argc, char* argv[]) {
// exchanged until the event loop starts running in the next line.
c.connect(con);

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
// this will cause a single connection to be made to the server. c.run()
// will exit when this connection is closed.
c.run();
Expand Down
2 changes: 1 addition & 1 deletion examples/echo_server/echo_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ int main() {
// Start the server accept loop
echo_server.start_accept(&on_end_accept);

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
echo_server.run();
} catch (websocketpp::exception const & e) {
std::cout << e.what() << std::endl;
Expand Down
14 changes: 7 additions & 7 deletions examples/echo_server_both/echo_server_both.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,22 @@ context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
}

int main() {
// set up an external io_service to run both endpoints on. This is not
// set up an external io_context to run both endpoints on. This is not
// strictly necessary, but simplifies thread management a bit.
boost::asio::io_service ios;
boost::asio::io_context ctx;

// set up plain endpoint
server_plain endpoint_plain;
// initialize asio with our external io_service rather than an internal one
endpoint_plain.init_asio(&ios);
// initialize asio with our external io_context rather than an internal one
endpoint_plain.init_asio(&ctx);
endpoint_plain.set_message_handler(
bind(&on_message<server_plain>,&endpoint_plain,::_1,::_2));
endpoint_plain.listen(80);
endpoint_plain.start_accept(&on_end_accept);

// set up tls endpoint
server_tls endpoint_tls;
endpoint_tls.init_asio(&ios);
endpoint_tls.init_asio(&ctx);
endpoint_tls.set_message_handler(
bind(&on_message<server_tls>,&endpoint_tls,::_1,::_2));
// TLS endpoint has an extra handler for the tls init
Expand All @@ -89,6 +89,6 @@ int main() {
endpoint_tls.listen(443);
endpoint_tls.start_accept(&on_end_accept);

// Start the ASIO io_service run loop running both endpoints
ios.run();
// Start the ASIO io_context run loop running both endpoints
ctx.run();
}
2 changes: 1 addition & 1 deletion examples/echo_server_tls/echo_server_tls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ int main() {
// Start the server accept loop
echo_server.start_accept(&on_end_accept);

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
echo_server.run();

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
file (GLOB SOURCE_FILES *.cpp)
file (GLOB HEADER_FILES *.hpp)

init_target (external_io_service)
init_target (external_io_context)

build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ prgs = []
# if a C++11 environment is available build using that, otherwise use boost
if 'WSPP_CPP11_ENABLED' in env_cpp11:
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
prgs += env_cpp11.Program('external_io_service', ["external_io_service.cpp"], LIBS = ALL_LIBS)
prgs += env_cpp11.Program('external_io_context', ["external_io_context.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('external_io_service', ["external_io_service.cpp"], LIBS = ALL_LIBS)
prgs += env.Program('external_io_context', ["external_io_context.cpp"], LIBS = ALL_LIBS)

Return('prgs')
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,19 @@ void on_end_accept(error_code lib_ec, error_code trans_ec) {
}

int main() {
asio::io_service service;
asio::io_context context;

// Add a TCP echo server on port 9003
tcp_echo_server custom_http_server(service, 9003);
tcp_echo_server custom_http_server(context, 9003);

// Add a WebSocket echo server on port 9002
ws_echo_server ws_server;
ws_server.set_access_channels(websocketpp::log::alevel::all);
ws_server.clear_access_channels(websocketpp::log::alevel::frame_payload);

// The only difference in this code between an internal and external
// io_service is the different constructor to init_asio
ws_server.init_asio(&service);
// io_context is the different constructor to init_asio
ws_server.init_asio(&context);

// Register our message handler
ws_server.set_message_handler(bind(&on_message,&ws_server,::_1,::_2));
Expand All @@ -87,6 +87,6 @@ int main() {

// TODO: add a timer?

// Start the Asio io_service run loop for all
service.run();
// Start the Asio io_context run loop for all
context.run();
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ namespace asio = websocketpp::lib::asio;
struct tcp_echo_session : websocketpp::lib::enable_shared_from_this<tcp_echo_session> {
typedef websocketpp::lib::shared_ptr<tcp_echo_session> ptr;

tcp_echo_session(asio::io_service & service) : m_socket(service) {}
tcp_echo_session(asio::io_context & context) : m_socket(context) {}

void start() {
m_socket.async_read_some(asio::buffer(m_buffer, sizeof(m_buffer)),
Expand Down Expand Up @@ -72,15 +72,15 @@ struct tcp_echo_session : websocketpp::lib::enable_shared_from_this<tcp_echo_ses
};

struct tcp_echo_server {
tcp_echo_server(asio::io_service & service, short port)
: m_service(service)
, m_acceptor(service, asio::ip::tcp::endpoint(asio::ip::tcp::v6(), port))
tcp_echo_server(asio::io_context & context, short port)
: m_context(context)
, m_acceptor(context, asio::ip::tcp::endpoint(asio::ip::tcp::v6(), port))
{
this->start_accept();
}

void start_accept() {
tcp_echo_session::ptr new_session(new tcp_echo_session(m_service));
tcp_echo_session::ptr new_session(new tcp_echo_session(m_context));
m_acceptor.async_accept(new_session->m_socket,
bind(&tcp_echo_server::handle_accept, this, new_session, _1));
}
Expand All @@ -92,6 +92,6 @@ struct tcp_echo_server {
start_accept();
}

asio::io_service & m_service;
asio::io_context & m_context;
asio::ip::tcp::acceptor m_acceptor;
};
2 changes: 1 addition & 1 deletion examples/print_client/print_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ int main(int argc, char* argv[]) {
// exchanged until the event loop starts running in the next line.
c.connect(con);

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
// this will cause a single connection to be made to the server. c.run()
// will exit when this connection is closed.
c.run();
Expand Down
2 changes: 1 addition & 1 deletion examples/print_client_tls/print_client_tls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ int main(int argc, char* argv[]) {

c.get_alog().write(websocketpp::log::alevel::app, "Connecting to " + uri);

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
// this will cause a single connection to be made to the server. c.run()
// will exit when this connection is closed.
c.run();
Expand Down
2 changes: 1 addition & 1 deletion examples/scratch_server/scratch_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ int main(int argc, char * argv[]) {
// Start the server accept loop
echo_server.start_accept();

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
echo_server.run();
} catch (websocketpp::exception const & e) {
std::cout << e.what() << std::endl;
Expand Down
2 changes: 1 addition & 1 deletion examples/sip_client/sip_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ int main(int argc, char* argv[]) {

sip_client.connect(con);

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
sip_client.run();

while(!received) {
Expand Down
4 changes: 2 additions & 2 deletions examples/telemetry_client/telemetry_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ class telemetry_client {
m_hdl = con->get_handle();

// Queue the connection. No DNS queries or network connections will be
// made until the io_service event loop is run.
// made until the io_context event loop is run.
m_client.connect(con);

// Create a thread to run the ASIO io_service event loop
// Create a thread to run the ASIO io_context event loop
websocketpp::lib::thread asio_thread(&client::run, &m_client);

// Create a thread to run the telemetry loop
Expand Down
2 changes: 1 addition & 1 deletion examples/telemetry_server/telemetry_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class telemetry_server {
// Set the initial timer to start telemetry
set_timer();

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
try {
m_endpoint.run();
} catch (websocketpp::exception const & e) {
Expand Down
4 changes: 2 additions & 2 deletions examples/testee_client/testee_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,13 @@ int main(int argc, char* argv[]) {
client::connection_ptr con = c.get_connection(uri+"/getCaseCount", ec);
c.connect(con);

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
c.run();

std::cout << "case count: " << case_count << std::endl;

for (int i = 1; i <= case_count; i++) {
c.reset();
c.restart();

std::stringstream url;

Expand Down
2 changes: 1 addition & 1 deletion examples/testee_server/testee_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ int main(int argc, char * argv[]) {
// Start the server accept loop
testee_server.start_accept(&on_end_accept);

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
if (num_threads == 1) {
testee_server.run();
} else {
Expand Down
2 changes: 1 addition & 1 deletion roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Complete & Tested:
- open_handler
- close_handler
- echo_server & echo_server_tls
- External io_service support
- External io_context support
- TLS support
- exception/error handling
- Timeouts
Expand Down
8 changes: 4 additions & 4 deletions test/endpoint/endpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ BOOST_AUTO_TEST_CASE( initialize_server_asio ) {

BOOST_AUTO_TEST_CASE( initialize_server_asio_external ) {
websocketpp::server<websocketpp::config::asio> s;
boost::asio::io_service ios;
s.init_asio(&ios);
boost::asio::io_context ctx;
s.init_asio(&ctx);
}

#ifdef _WEBSOCKETPP_MOVE_SEMANTICS_
Expand Down Expand Up @@ -141,8 +141,8 @@ BOOST_AUTO_TEST_CASE( listen_after_listen_failure ) {
server1.init_asio();
server2.init_asio();

boost::asio::ip::tcp::endpoint ep1(boost::asio::ip::address::from_string("127.0.0.1"), 12345);
boost::asio::ip::tcp::endpoint ep2(boost::asio::ip::address::from_string("127.0.0.1"), 23456);
boost::asio::ip::tcp::endpoint ep1(boost::asio::ip::make_address("127.0.0.1"), 12345);
boost::asio::ip::tcp::endpoint ep2(boost::asio::ip::make_address("127.0.0.1"), 23456);

server1.listen(ep1, ec);
BOOST_CHECK(!ec);
Expand Down
10 changes: 5 additions & 5 deletions test/transport/asio/timers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ void run_dummy_server(int port) {
using boost::asio::ip::tcp;

try {
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v6(), port));
tcp::socket socket(io_service);
boost::asio::io_context io_context;
tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v6(), port));
tcp::socket socket(io_context);

acceptor.accept(socket);
for (;;) {
Expand All @@ -79,8 +79,8 @@ void run_dummy_server(int port) {

// Wait for the specified time period then fail the test
void run_test_timer(long value) {
boost::asio::io_service ios;
boost::asio::deadline_timer t(ios,boost::posix_time::milliseconds(value));
boost::asio::io_context ctx;
boost::asio::deadline_timer t(ctx,boost::posix_time::milliseconds(value));
boost::system::error_code ec;
t.wait(ec);
BOOST_FAIL( "Test timed out" );
Expand Down
Loading