### Main Application Entry Point with asio3 Source: https://context7.com/zhllxt/asio3/llms.txt Sets up the Asio I/O context, creates an HTTP client, and starts asynchronous operations for connecting and handling signals. It runs the Asio event loop until interrupted. Requires the asio3 library and standard C++ headers. ```cpp #include #include namespace net = asio; int main() { net::io_context ctx{ 1 }; net::http_client client(ctx.get_executor()); net::co_spawn(ctx.get_executor(), connect(client), net::detached); net::signal_set sigset(ctx.get_executor(), SIGINT); sigset.async_wait([&client](net::error_code, int) mutable { client.async_stop([](auto) {}); }); ctx.run(); } ``` -------------------------------- ### Enable Testing and Include Example Directory (CMake) Source: https://github.com/zhllxt/asio3/blob/main/CMakeLists.txt This snippet enables the testing infrastructure for the project using `enable_testing()`. It also conditionally includes the `example` subdirectory if the `BUILD_EXAMPLES` option is set to true. This allows for building and testing example applications alongside the main library. ```cmake enable_testing() # after test, i find that it will linked failed on MINGW when use the static ssl librarys, # but it will successed when use the shared ssl librarys like this: # https://github.com/axmolengine/buildware/releases/tag/v41 if (BUILD_EXAMPLES) #include_directories (/usr/local/include) # for boost header file include #include_directories (D:/boost) # for boost header file include include_directories (${ASIO3_ROOT_DIR}/3rd) include_directories (${ASIO3_ROOT_DIR}/3rd/openssl/include) include_directories (${ASIO3_ROOT_DIR}/include) #link_directories (/usr/local/lib) # for boost library file include #link_directories (D:/boost/stage/lib) # for boost library file include add_subdirectory (example) endif(BUILD_EXAMPLES) ``` -------------------------------- ### C++ HTTP Server with Routing and Static File Serving Source: https://context7.com/zhllxt/asio3/llms.txt This C++ code implements a basic HTTP server using asio3. It handles incoming requests, routes them based on URLs, serves static files from a specified webroot, and supports keep-alive connections. It also includes a 404 response handler and an example of a custom router. ```cpp #include #include namespace net = asio; net::awaitable do_http_recv(net::http_server& server, std::shared_ptr session) { beast::flat_buffer buf; for (;;) { http::web_request req; auto [e1, n1] = co_await http::async_read(session->socket, buf, req); if (e1) break; session->update_alive_time(); http::web_response rep; bool result = co_await server.router.route(req, rep); auto [e2, n2] = co_await beast::async_write(session->socket, std::move(rep)); if (e2) break; if (!result || !req.keep_alive()) break; } session->close(); } net::awaitable client_join(net::http_server& server, std::shared_ptr session) { auto addr = session->get_remote_address(); auto port = session->get_remote_port(); fmt::print("+ client join: {} {}\n", addr, port); co_await server.session_map.async_add(session); co_await(do_http_recv(server, session) || net::watchdog(session->alive_time, net::http_idle_timeout)); co_await server.session_map.async_remove(session); fmt::print("- client exit: {} {}\n", addr, port); } net::awaitable start_server(net::http_server& server, std::string listen_address, std::uint16_t listen_port) { auto [ec, ep] = co_await server.async_listen(listen_address, listen_port); if (ec) { fmt::print("listen failure: {}\n", ec.message()); co_return; } fmt::print("listen success: {} {}\n", server.get_listen_address(), server.get_listen_port()); while (!server.is_aborted()) { auto [e1, client] = co_await server.acceptor.async_accept(); if (e1) { co_await net::delay(std::chrono::milliseconds(100)); } else { net::co_spawn(server.get_executor(), client_join(server, std::make_shared(std::move(client))), net::detached); } } } auto response_404() { return http::make_error_page_response(http::status::not_found); } struct aop_auth { net::awaitable before(http::web_request& req, http::web_response& rep) { if (req.find(http::field::authorization) == req.end()) { rep = response_404(); co_return false; } co_return true; } }; int main() { net::io_context_thread ctx; net::http_server server(ctx.get_executor()); std::filesystem::path root = std::filesystem::current_path(); root = root.parent_path().parent_path().append("example/wwwroot"); server.webroot = std::move(root); server.router.add("/", [&server](http::web_request& req, http::web_response& rep) -> net::awaitable { auto res = http::make_file_response(server.webroot, "/index.html"); if (res.has_value()) rep = std::move(res.value()); else rep = response_404(); co_return true; }, http::enable_cache); server.router.add("/login", [](http::web_request& req, http::web_response& rep) -> net::awaitable { rep = response_404(); co_return true; }, aop_auth{}); server.router.add("*", [&server](http::web_request& req, http::web_response& rep) -> net::awaitable { auto res = http::make_file_response(server.webroot, req.target()); if (res.has_value()) rep = std::move(res.value()); else rep = response_404(); co_return true; }, http::enable_cache); net::co_spawn(ctx.get_executor(), start_server(server, "0.0.0.0", 8080), net::detached); net::signal_set sigset(ctx.get_executor(), SIGINT); sigset.async_wait([&server](net::error_code, int) mutable { server.async_stop([](auto) {}); }); ctx.join(); } ``` -------------------------------- ### HTTP Client File Download using C++ asio3 Source: https://context7.com/zhllxt/asio3/llms.txt Performs streaming downloads of a file from an HTTP server. It creates a local file for writing, sends an HTTP GET request, and asynchronously receives and saves the file content with progress tracking. Requires the asio3 library. ```cpp #include #include namespace net = asio; net::awaitable do_download(net::http_client& client) { beast::flat_buffer buffer; auto on_chunk = [](auto) { return true; }; net::error_code ec{}; net::stream_file file(client.get_executor()); file.open("downloaded.zip", net::file_base::write_only | net::file_base::create | net::file_base::truncate, ec); if (ec) co_return; http::request req{ http::verb::get, "/", 11 }; req.target("/download/data.zip"); req.set(http::field::host, "127.0.0.1:8080"); auto [e1, n1] = co_await http::async_write(client.socket, req); if (e1) co_return; http::response_parser parser; parser.body_limit((std::numeric_limits::max)()); auto [e2, n2] = co_await http::async_read_header(client.socket, buffer, parser); if (e2) co_return; auto [e3, n3] = co_await http::async_recv_file(client.socket, file, buffer, parser.get(), on_chunk); fmt::print("download finished: {}\n", e3.message()); client.close(); } ``` -------------------------------- ### Define TCP Server Executable using CMake Source: https://github.com/zhllxt/asio3/blob/main/example/ssl/tcp/server/CMakeLists.txt This snippet defines the 'tcps_server' executable using CMake. It lists the source files required for the executable and specifies the target name. The executable is then placed in the 'example' folder for better organization. ```cmake aux_source_directory(. SRC_FILES) source_group("" FILES ${SRC_FILES}) set(TARGET_NAME tcps_server) add_executable ( ${TARGET_NAME} ${ASIO3_FILES} ${TARGET_NAME}.cpp ) set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "example") ``` -------------------------------- ### Define TCP Client Executable Target Source: https://github.com/zhllxt/asio3/blob/main/example/tcp/client/CMakeLists.txt This snippet defines an executable target named 'tcp_client' and lists the source files required for its compilation. It includes custom ASIO3 files and a main C++ source file. The target is organized within the 'example' folder in build environments. ```cmake set(TARGET_NAME tcp_client) add_executable ( ${TARGET_NAME} ${ASIO3_FILES} ${TARGET_NAME}.cpp ) set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "example") ``` -------------------------------- ### Include Server Subdirectory (CMake) Source: https://github.com/zhllxt/asio3/blob/main/example/udp/CMakeLists.txt This CMake command incorporates the 'server' subdirectory into the build process, enabling the compilation and linking of server-related components. This promotes code organization and modularity. ```cmake add_subdirectory (server) ``` -------------------------------- ### Include Client Subdirectory (CMake) Source: https://github.com/zhllxt/asio3/blob/main/example/udp/CMakeLists.txt This CMake command includes the 'client' subdirectory, allowing for the compilation and integration of client-specific code. It is a standard way to manage modular projects in CMake. ```cmake add_subdirectory (client) ``` -------------------------------- ### Create and Configure HTTPS Server with SSL/TLS - C++ Source: https://context7.com/zhllxt/asio3/llms.txt This C++ code snippet sets up an HTTPS server using Asio3. It configures SSL/TLS contexts, loads certificate files, defines a request router for serving static content, and initiates the server to listen on a specified address and port. It also includes signal handling for graceful shutdown. ```cpp #ifndef ASIO3_ENABLE_SSL #define ASIO3_ENABLE_SSL #endif #include #include namespace net = asio; net::awaitable do_http_recv(net::https_server& server, std::shared_ptr session) { beast::flat_buffer buf; for (;;) { http::web_request req; auto [e1, n1] = co_await http::async_read(session->ssl_stream, buf, req); if (e1) break; session->update_alive_time(); http::web_response rep; bool result = co_await server.router.route(req, rep); auto [e2, n2] = co_await beast::async_write(session->ssl_stream, std::move(rep)); if (e2) break; if (!result || !req.keep_alive()) break; } co_await session->ssl_stream.async_shutdown(); session->close(); } net::awaitable client_join(net::https_server& server, std::shared_ptr session) { session->socket.set_option(net::ip::tcp::no_delay(true)); session->socket.set_option(net::socket_base::keep_alive(true)); auto [e2] = co_await net::async_handshake(session->ssl_stream, net::ssl::stream_base::handshake_type::server); if (e2) { fmt::print("handshake failure: {}\n", e2.message()); co_return; } auto addr = session->get_remote_address(); auto port = session->get_remote_port(); fmt::print("+ client join: {} {}\n", addr, port); co_await server.session_map.async_add(session); co_await(do_http_recv(server, session) || net::watchdog(session->alive_time, net::http_idle_timeout)); co_await server.session_map.async_remove(session); fmt::print("- client exit: {} {}\n", addr, port); } net::awaitable start_server(net::https_server& server, std::string listen_address, std::uint16_t listen_port) { auto [ec, ep] = co_await server.async_listen(listen_address, listen_port); if (ec) { fmt::print("listen failure: {}\n", ec.message()); co_return; } fmt::print("listen success: {} {}\n", server.get_listen_address(), server.get_listen_port()); while (!server.is_aborted()) { auto [e1, client] = co_await server.acceptor.async_accept(); if (e1) { co_await net::delay(std::chrono::milliseconds(100)); } else { net::co_spawn(server.get_executor(), client_join(server, std::make_shared(std::move(client), server.ssl_context)), net::detached); } } } int main() { net::io_context_thread ctx; net::https_server server(ctx.get_executor()); server.ssl_context.set_options( net::ssl::context::default_workarounds | net::ssl::context::no_sslv2 | net::ssl::context::single_dh_use); server.ssl_context.use_certificate_chain_file("server.crt"); server.ssl_context.use_private_key_file("server.key", net::ssl::context::pem); server.ssl_context.use_tmp_dh_file("dh2048.pem"); std::filesystem::path root = std::filesystem::current_path(); server.webroot = std::move(root); server.router.add("*", [&server](http::web_request& req, http::web_response& rep) -> net::awaitable { auto res = http::make_file_response(server.webroot, req.target()); if (res.has_value()) rep = std::move(res.value()); else rep = http::make_error_page_response(http::status::not_found); co_return true; }); net::co_spawn(ctx.get_executor(), start_server(server, "0.0.0.0", 8443), net::detached); net::signal_set sigset(ctx.get_executor(), SIGINT); sigset.async_wait([&server](net::error_code, int) mutable { server.async_stop([](auto) {}); }); ctx.join(); } ``` -------------------------------- ### Include Cast Subdirectory (CMake) Source: https://github.com/zhllxt/asio3/blob/main/example/udp/CMakeLists.txt This CMake command adds the 'cast' subdirectory to the project, facilitating the inclusion of casting-related functionalities into the build. It supports the modular development of the Asio3 project. ```cmake add_subdirectory (cast) ``` -------------------------------- ### CMake: Project Configuration and Options Source: https://github.com/zhllxt/asio3/blob/main/CMakeLists.txt This snippet defines the project name as 'asio3', enables folder view in IDEs, and sets boolean options for building examples (`BUILD_EXAMPLES`) and tests (`BUILD_TESTS`). These options allow users to customize the build process. ```cmake project (asio3) set_property (GLOBAL PROPERTY USE_FOLDERS ON) option(BUILD_EXAMPLES "Build examples" OFF) option(BUILD_TESTS "Build tests" OFF) ``` -------------------------------- ### Define Executable Target - CMake Source: https://github.com/zhllxt/asio3/blob/main/example/icmp/CMakeLists.txt Defines an executable target with the specified name and source files. It includes source files from the current directory and other specified lists. ```cmake set(TARGET_NAME icmp_ping) add_executable ( ${TARGET_NAME} ${ASIO3_FILES} ${TARGET_NAME}.cpp ) ``` -------------------------------- ### C++ RPC Server Implementation Source: https://context7.com/zhllxt/asio3/llms.txt This C++ code implements an RPC server using the asio3 library. It includes functions for handling client connections, receiving and processing RPC requests, and sending responses. Dependencies include ``, ``, and ``. The server binds specific functions (`echo`, `add`) and manages sessions in a multi-threaded environment. ```cpp #include #include #include namespace net = asio; net::awaitable echo(std::string a) { co_return a; } net::awaitable add(int a, int b) { co_return a + b; } net::awaitable do_recv(net::rpc_server& server, std::shared_ptr session) { std::string strbuf; rpc::serializer& sr = session->serializer; rpc::deserializer& dr = session->deserializer; for (;;) { auto [e1, n1] = co_await net::async_read_until( session->get_stream(), net::dynamic_buffer(strbuf), net::length_payload_match_condition{}); if (e1) break; if (n1 == 0) break; session->update_alive_time(); std::string_view data = net::length_payload_match_condition::get_payload(strbuf.data(), n1); rpc::header head{}; try { dr.reset(data); dr >> head; } catch (const cereal::exception&) { break; } if (head.is_request()) { auto [e2, resp] = co_await server.invoker.invoke(sr, dr, std::move(head), data); if (!resp.empty()) { std::string len = asio::length_payload_match_condition::generate_length(asio::buffer(resp)); std::array buffers { asio::buffer(len), asio::buffer(resp), }; co_await session->async_send(buffers); } if (e2) break; } else if (head.is_response()) { co_await session->async_notify(sr, dr, std::move(head), data); } else { break; } strbuf.erase(0, n1); } session->close(); } net::awaitable client_join(net::rpc_server& server, std::shared_ptr session) { co_await server.session_map.async_add(session); co_await(do_recv(server, session) || net::watchdog(session->alive_time, net::tcp_idle_timeout)); co_await server.session_map.async_remove(session); } net::awaitable start_server( std::vector& session_ctxs, net::rpc_server& server, std::string listen_address, std::uint16_t listen_port) { auto [ec, ep] = co_await server.async_listen(listen_address, listen_port); if (ec) { fmt::print("listen failure: {}\n", ec.message()); co_return; } fmt::print("listen success: {} {}\n", server.get_listen_address(), server.get_listen_port()); std::size_t next = 0; while (!server.is_aborted()) { const auto& ex = session_ctxs.at((next++) % session_ctxs.size()).get_executor(); auto [e1, client] = co_await server.acceptor.async_accept(ex); if (e1) { co_await net::delay(std::chrono::milliseconds(100)); } else { net::co_spawn(ex, client_join(server, std::make_shared(std::move(client))), net::detached); } } } int main() { net::io_context listen_ctx{ 1 }; std::vector session_ctxs{ std::thread::hardware_concurrency() * 2 }; net::rpc_server server(listen_ctx.get_executor()); server.invoker.bind("echo", echo); server.invoker.bind("add", add); net::co_spawn(listen_ctx.get_executor(), start_server(session_ctxs, server, "0.0.0.0", 8038), net::detached); net::signal_set sigset(listen_ctx.get_executor(), SIGINT); sigset.async_wait([&server](net::error_code, int) mutable { server.async_stop([](auto) {}); }); listen_ctx.run(); for (auto& session_ctx : session_ctxs) { session_ctx.join(); } } ``` -------------------------------- ### C++ RPC Client Connection and Request Handling - Asio3 Source: https://context7.com/zhllxt/asio3/llms.txt Establishes an RPC client connection and handles incoming messages. It deserializes RPC headers and routes responses. This function runs in a loop, maintaining the connection and processing messages. ```cpp #include #include #include namespace net = asio; net::awaitable do_recv(net::rpc_client& client) { std::string strbuf; rpc::serializer& sr = client.serializer; rpc::deserializer& dr = client.deserializer; for (;;) { auto [e1, n1] = co_await net::async_read_until( client.get_stream(), net::dynamic_buffer(strbuf), net::length_payload_match_condition{}); if (e1) break; std::string_view data = net::length_payload_match_condition::get_payload(strbuf.data(), n1); rpc::header head{}; try { dr.reset(data); dr >> head; } catch (const cereal::exception&) { break; } if (head.is_response()) { co_await client.async_notify(sr, dr, std::move(head), data); } else { break; } strbuf.erase(0, n1); } client.close(); } net::awaitable connect(net::rpc_client& client) { while (!client.is_aborted()) { auto [ec, ep] = co_await client.async_connect("127.0.0.1", 8038); if (ec) { fmt::print("connect failure: {}\n", ec.message()); co_await net::delay(std::chrono::seconds(1)); client.close(); continue; } fmt::print("connect success: {} {}\n", client.get_remote_address(), client.get_remote_port()); net::co_spawn(client.get_executor(), [&client]() mutable -> net::awaitable { for (;;) { auto [e1, result] = co_await client .set_request_option({ .timeout = std::chrono::seconds(3) }) .async_call("echo", "Hello RPC"); if (e1) break; fmt::print("RPC result: {}\n", result); auto [e2, sum] = co_await client .set_request_option({ .timeout = std::chrono::seconds(3) }) .async_call("add", 10, 20); if (e2) break; fmt::print("RPC sum: {}\n", sum); co_await net::delay(std::chrono::seconds(1)); } }, net::detached); co_await do_recv(client); } } int main() { net::io_context ctx{ 1 }; net::rpc_client client(ctx.get_executor()); net::co_spawn(ctx.get_executor(), connect(client), net::detached); net::signal_set sigset(ctx.get_executor(), SIGINT); sigset.async_wait([&client](net::error_code, int) mutable { client.async_stop([](auto) {}); }); ctx.run(); } ``` -------------------------------- ### HTTP Client File Upload using C++ asio3 Source: https://context7.com/zhllxt/asio3/llms.txt Handles chunked file uploads to an HTTP server. It opens a file for reading, sets up an HTTP POST request with chunked encoding, and asynchronously sends the file content. Requires the asio3 library. ```cpp #include #include namespace net = asio; net::awaitable do_upload(net::http_client& client) { beast::flat_buffer buffer; auto on_chunk = [](auto) { return true; }; net::error_code ec{}; net::stream_file file(client.get_executor()); file.open("data.zip", net::file_base::read_only, ec); if (ec) co_return; http::request req{ http::verb::post, "/", 11 }; req.target("/upload/data.zip"); req.set(http::field::content_type, http::extension_to_mimetype("zip")); req.set(http::field::host, "127.0.0.1:8080"); req.chunked(true); auto [e0, n0] = co_await http::async_send_file(client.socket, file, req, on_chunk); fmt::print("upload finished: {}\n", e0.message()); http::response res; auto [e1, n1] = co_await http::async_read(client.socket, buffer, res); client.close(); } ``` -------------------------------- ### Find Source Files - CMake Source: https://github.com/zhllxt/asio3/blob/main/example/icmp/CMakeLists.txt Automatically finds all source files in a directory and stores them in a variable. This is a common pattern for managing source files in CMake projects. ```cmake aux_source_directory(. SRC_FILES) ``` -------------------------------- ### UDP Server with Session Management in C++ Source: https://context7.com/zhllxt/asio3/llms.txt Implements a UDP server that automatically creates sessions for unique client endpoints. It manages session timeouts using watchdog timers and handles client disconnections. Dependencies include asio3/udp/udp_server.hpp and asio3/core/fmt.hpp. It listens on a specified address and port, processes incoming datagrams, and sends responses. ```cpp #include #include namespace net = asio; net::awaitable client_join(net::udp_server& server, std::shared_ptr session) { co_await net::watchdog(session->watchdog_timer, session->alive_time, net::udp_idle_timeout); co_await session->async_disconnect(); co_await server.session_map.async_remove(session); } net::awaitable start_server(net::udp_server& server, std::string listen_address, std::uint16_t listen_port) { auto [ec, ep] = co_await server.async_open(listen_address, listen_port); if (ec) { fmt::print("listen failure: {}\n", ec.message()); co_return; } fmt::print("listen success: {} {}\n", server.get_listen_address(), server.get_listen_port()); std::array buf; net::ip::udp::endpoint remote_endpoint{}; while (!server.is_aborted()) { auto [e1, n1] = co_await net::async_receive_from( server.socket, net::buffer(buf), remote_endpoint); if (e1) break; auto [session] = co_await server.session_map.async_find(remote_endpoint); if (!session) { session = net::udp_session::create(server.socket, remote_endpoint); co_await server.session_map.async_add(session); net::co_spawn(server.get_executor(), client_join(server, session), net::detached); } session->update_alive_time(); auto data = net::buffer(buf.data(), n1); fmt::print("{} {} {} {}\n", std::chrono::system_clock::now(), session->get_remote_address(), session->get_remote_port(), data); co_await session->async_send(data); } } int main() { net::io_context_thread ctx; net::udp_server server(ctx.get_executor()); net::co_spawn(server.get_executor(), start_server(server, "0.0.0.0", 8035), net::detached); net::signal_set sigset(ctx.get_executor(), SIGINT); sigset.async_wait([&server](net::error_code, int) mutable { server.async_stop([](auto) {}); }); ctx.join(); } ``` -------------------------------- ### C++ WebSocket Server Implementation with Asio3 Source: https://context7.com/zhllxt/asio3/llms.txt This C++ code implements a WebSocket server using the Asio3 library. It handles client connections, performs WebSocket handshakes, and echoes received messages. The server automatically detects message types (text/binary) and manages client sessions, including keep-alive and idle timeouts. It also gracefully handles shutdown signals. ```cpp #include #include namespace net = asio; net::awaitable do_recv(std::shared_ptr session) { beast::flat_buffer buf; for (;;) { auto [e1, n1] = co_await session->ws_stream.async_read(buf); if (e1) break; session->update_alive_time(); session->ws_stream.text(session->ws_stream.got_text()); auto [e2, n2] = co_await net::async_send(session->ws_stream, buf.data()); if (e2) break; buf.consume(buf.size()); } session->close(); } net::awaitable client_join(net::ws_server& server, std::shared_ptr session) { session->ws_stream.set_option(websocket::stream_base::timeout::suggested(beast::role_type::server)); session->ws_stream.set_option(websocket::stream_base::decorator( [](websocket::response_type& res) { res.set(http::field::server, BEAST_VERSION_STRING); })); auto [e0] = co_await session->ws_stream.async_accept(); if (e0) { fmt::print("websocket handshake failed: {} {} {{}}\n", session->get_remote_address(), session->get_remote_port(), e0.message()); co_return; } auto addr = session->get_remote_address(); auto port = session->get_remote_port(); fmt::print("+ websocket client join: {} {{}}\n", addr, port); co_await server.session_map.async_add(session); session->socket.set_option(net::ip::tcp::no_delay(true)); session->socket.set_option(net::socket_base::keep_alive(true)); co_await(do_recv(session) || net::watchdog(session->alive_time, net::tcp_idle_timeout)); co_await server.session_map.async_remove(session); fmt::print("- websocket client exit: {} {{}}\n", addr, port); } net::awaitable start_server(net::ws_server& server, std::string listen_address, std::uint16_t listen_port) { auto [ec, ep] = co_await server.async_listen(listen_address, listen_port); if (ec) { fmt::print("listen failure: {{}}\n", ec.message()); co_return; } fmt::print("listen success: {} {{}}\n", server.get_listen_address(), server.get_listen_port()); while (!server.is_aborted()) { auto [e1, client] = co_await server.acceptor.async_accept(); if (e1) { co_await net::delay(std::chrono::milliseconds(100)); } else { net::co_spawn(server.get_executor(), client_join(server, std::make_shared(std::move(client))), net::detached); } } } int main() { net::io_context_thread ctx; net::ws_server server(ctx.get_executor()); net::co_spawn(ctx.get_executor(), start_server(server, "0.0.0.0", 8080), net::detached); net::signal_set sigset(ctx.get_executor(), SIGINT); sigset.async_wait([&server](net::error_code, int) mutable { server.async_stop([](auto) {}); }); ctx.join(); } ``` -------------------------------- ### Configure Debugging and Linking for TCP Server with CMake Source: https://github.com/zhllxt/asio3/blob/main/example/ssl/tcp/server/CMakeLists.txt This snippet configures build properties for the 'tcps_server' executable. It sets the working directory for the Visual Studio debugger and adds specific linker flags for MSVC builds. It also links against necessary directories and libraries. ```cmake set_target_properties(${TARGET_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${ASIO3_EXES_DIR}) if (MSVC) set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "/ignore:4099") endif() target_link_directories(${TARGET_NAME} PRIVATE ${ASIO3_LIBS_DIR}) target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(${TARGET_NAME} ${GENERAL_LIBS}) target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBS}) ``` -------------------------------- ### HTTP Client Connection Management using C++ asio3 Source: https://context7.com/zhllxt/asio3/llms.txt Manages the connection to an HTTP server, including automatic reconnections on failure. It continuously attempts to connect and, upon success, initiates download operations. Requires the asio3 library. ```cpp #include #include namespace net = asio; net::awaitable connect(net::http_client& client) { while (!client.is_aborted()) { auto [ec, ep] = co_await client.async_connect("127.0.0.1", 8080); if (ec) { fmt::print("connect failure: {}\n", ec.message()); co_await net::delay(std::chrono::seconds(1)); client.close(); continue; } fmt::print("connect success: {} {}\n", client.get_remote_address(), client.get_remote_port()); co_await do_download(client); } } ``` -------------------------------- ### C++ TCP Client Implementation with asio3 Source: https://context7.com/zhllxt/asio3/llms.txt This C++ code demonstrates a TCP client using the asio3 library, capable of connecting to a server, sending data, and receiving responses. It features automatic reconnection upon connection failure and integrates C++20 coroutines for asynchronous operations. The client requires the asio3 library and a C++20 compatible compiler. ```cpp #include #include namespace net = asio; net::awaitable do_recv(net::tcp_client& client) { std::string strbuf; for (;;) { auto [e1, n1] = co_await net::async_read_until(client.socket, net::dynamic_buffer(strbuf), '\n'); if (e1) break; auto data = net::buffer(strbuf.data(), n1); fmt::print("Response: {}\n", data); auto [e2, n2] = co_await net::async_send(client.socket, data); if (e2) break; strbuf.erase(0, n1); } client.close(); } net::awaitable connect(net::tcp_client& client) { while (!client.is_aborted()) { auto [ec, ep] = co_await client.async_connect("127.0.0.1", 8028); if (ec) { fmt::print("connect failure: {}\n", ec.message()); co_await net::delay(std::chrono::seconds(1)); client.close(); continue; } fmt::print("connect success: {} {}\n", client.get_remote_address(), client.get_remote_port()); co_await client.async_send("Hello Server\n"); co_await do_recv(client); } } int main() { net::io_context ctx{ 1 }; net::tcp_client client(ctx.get_executor()); net::co_spawn(ctx.get_executor(), connect(client), net::detached); net::signal_set sigset(ctx.get_executor(), SIGINT); sigset.async_wait([&client](net::error_code, int) mutable { client.async_stop([](auto) {}); }); ctx.run(); } ``` -------------------------------- ### Configure TCP Client Debugging and Linking Source: https://github.com/zhllxt/asio3/blob/main/example/tcp/client/CMakeLists.txt This CMake configuration sets the working directory for the debugger when running the 'tcp_client' executable and links the necessary thread and general libraries. This ensures the client can find its dependencies at runtime. ```cmake set_target_properties(${TARGET_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${ASIO3_EXES_DIR}) target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(${TARGET_NAME} ${GENERAL_LIBS}) ``` -------------------------------- ### Group Source Files - CMake Source: https://github.com/zhllxt/asio3/blob/main/example/icmp/CMakeLists.txt Groups source files within specified directories for better organization in build systems like Visual Studio. It helps categorize files under specific headings in the project explorer. ```cmake GroupSources (include/asio3 ") GroupSources (3rd/asio ") ``` -------------------------------- ### C++ TCP Server Implementation with asio3 Source: https://context7.com/zhllxt/asio3/llms.txt This C++ code implements a TCP server using the asio3 library. It listens for incoming connections, echoes received data back to clients, and includes features like session management and keepalive. The server integrates with ASIO and C++20 coroutines for asynchronous operations. It requires the asio3 library and a C++20 compatible compiler. ```cpp #include #include namespace net = asio; net::awaitable do_recv(std::shared_ptr session) { std::string strbuf; for (;;) { auto [e1, n1] = co_await net::async_read_until(session->socket, net::dynamic_buffer(strbuf), '\n'); if (e1) break; session->update_alive_time(); auto data = net::buffer(strbuf.data(), n1); fmt::print("Received: {}\n", data); auto [e2, n2] = co_await net::async_send(session->socket, data); if (e2) break; strbuf.erase(0, n1); } session->close(); } net::awaitable client_join(net::tcp_server& server, std::shared_ptr session) { co_await server.session_map.async_add(session); session->socket.set_option(net::ip::tcp::no_delay(true)); session->socket.set_option(net::socket_base::keep_alive(true)); co_await(do_recv(session) || net::watchdog(session->alive_time, net::tcp_idle_timeout)); co_await server.session_map.async_remove(session); } net::awaitable start_server(net::tcp_server& server, std::string listen_address, std::uint16_t listen_port) { auto [ec, ep] = co_await server.async_listen(listen_address, listen_port); if (ec) { fmt::print("listen failure: {}\n", ec.message()); co_return; } fmt::print("listen success: {} {}\n", server.get_listen_address(), server.get_listen_port()); while (!server.is_aborted()) { auto [e1, client] = co_await server.acceptor.async_accept(); if (e1) { co_await net::delay(std::chrono::milliseconds(100)); } else { net::co_spawn(server.get_executor(), client_join(server, std::make_shared(std::move(client))), net::detached); } } } int main() { net::io_context_thread ctx; net::tcp_server server(ctx.get_executor()); net::co_spawn(ctx.get_executor(), start_server(server, "0.0.0.0", 8028), net::detached); net::signal_set sigset(ctx.get_executor(), SIGINT); sigset.async_wait([&server](net::error_code, int) mutable { server.async_stop([](auto) {}); }); ctx.join(); } ``` -------------------------------- ### Set Target Properties (CMake) Source: https://github.com/zhllxt/asio3/blob/main/example/serial_port/CMakeLists.txt These CMake commands set properties for the 'serial_port' target. It places the target in the 'example' folder and configures the VS debugger's working directory. This aids in organizing build targets and debugging. ```cmake set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "example") set_target_properties(${TARGET_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${ASIO3_EXES_DIR}) ``` -------------------------------- ### ICMP Ping Utility in C++ Source: https://context7.com/zhllxt/asio3/llms.txt Sends ICMP echo requests to a specified host and prints ping statistics, including round-trip time (RTT), time-to-live (TTL), and sequence numbers. It uses a loop to continuously send pings every second. Dependencies include asio3/icmp/ping.hpp and asio3/core/fmt.hpp. The function `do_ping` handles sending requests and parsing replies, with a timeout mechanism. ```cpp #include #include namespace net = asio; net::awaitable do_ping(std::string host) { for (;;) { auto [ec, rep] = co_await net::co_ping(host); if (rep.is_timeout()) fmt::print("request timed out: {}\n", ec.message()); else fmt::print("{} bytes from {}: icmp_seq={}, ttl={}, time={}ms\n", rep.total_length() - rep.header_length(), rep.source_address().to_string(), rep.sequence_number(), rep.time_to_live(), rep.milliseconds() ); co_await net::delay(std::chrono::seconds(1)); } } int main() { net::io_context ctx{ 1 }; net::co_spawn(ctx.get_executor(), do_ping("www.google.com"), net::detached); net::signal_set sigset(ctx.get_executor(), SIGINT); sigset.async_wait([&ctx](net::error_code, int) mutable { ctx.stop(); }); ctx.run(); } ``` -------------------------------- ### Set Target Properties in CMake Source: https://github.com/zhllxt/asio3/blob/main/example/ssl/tcp/client/CMakeLists.txt This CMake code sets various properties for a target. It places the target into a 'example' folder and configures the Visual Studio debugger to use a specific working directory. It also includes a conditional linker flag for MSVC to ignore a specific warning. ```cmake set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "example") set_target_properties(${TARGET_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${ASIO3_EXES_DIR}) if (MSVC) set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "/ignore:4099") endif() ``` -------------------------------- ### Get Error Message from Parse Error (C++) Source: https://github.com/zhllxt/asio3/blob/main/3rd/cereal/external/rapidxml/manual.html Returns a null-terminated string describing the parsing error. This method is part of the std::exception interface. ```C++ virtual const char* what() const; ``` -------------------------------- ### Get Next Sibling Node - C++ Source: https://github.com/zhllxt/asio3/blob/main/3rd/cereal/external/rapidxml/manual.html Retrieves the next sibling node, optionally filtering by name. Behavior is undefined if the node has no parent. Case-sensitive comparison is limited to ASCII characters. ```cpp xml_node* next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; ``` -------------------------------- ### Get Previous Sibling Node - C++ Source: https://github.com/zhllxt/asio3/blob/main/3rd/cereal/external/rapidxml/manual.html Retrieves the previous sibling node, optionally filtering by name. Behavior is undefined if the node has no parent. Case-sensitive comparison is limited to ASCII characters. ```cpp xml_node* previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; ``` -------------------------------- ### Get Error Location from Parse Error (C++) Source: https://github.com/zhllxt/asio3/blob/main/3rd/cereal/external/rapidxml/manual.html Returns a pointer to the character in the source text where the parsing error occurred. The type Ch should match the character type used by the xml_document. ```C++ Ch* where() const; ``` -------------------------------- ### RapidXML: XML Node Navigation and Manipulation Source: https://github.com/zhllxt/asio3/blob/main/3rd/cereal/external/rapidxml/manual.html Illustrates common operations for navigating and modifying RapidXML nodes, including finding nodes and attributes, and adding/removing children. Assumes an existing xml_node object. ```cpp // Assuming 'node' is a valid rapidxml::xml_node* // Find first child node named "child" rapidxml::xml_node* child_node = node->first_node("child"); // Find first attribute named "id" rapidxml::xml_attribute* id_attribute = node->first_attribute("id"); // Append a new node (assuming 'new_child_node' is created) // node->append_node(new_child_node); // Remove the first node // node->remove_first_node(); ``` -------------------------------- ### Get Parent Node - C++ Source: https://github.com/zhllxt/asio3/blob/main/3rd/cereal/external/rapidxml/manual.html Retrieves a pointer to the parent node of the current node. If the node is the root or has no parent, it returns a null pointer (0). This is essential for navigating the XML tree structure. ```cpp xml_node* parent() const; ``` -------------------------------- ### Get First Attribute Node - C++ Source: https://github.com/zhllxt/asio3/blob/main/3rd/cereal/external/rapidxml/manual.html Retrieves the first attribute of a node, optionally filtering by name. The `name_size` parameter allows for specifying the name length, with 0 indicating automatic calculation. Case sensitivity is applicable. ```cpp xml_attribute* first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; ``` -------------------------------- ### Get Last Attribute Node - C++ Source: https://github.com/zhllxt/asio3/blob/main/3rd/cereal/external/rapidxml/manual.html Retrieves the last attribute of a node, optionally filtering by name. Similar to `first_attribute`, it supports specifying `name_size` and case sensitivity. If `name` is 0, the last attribute is returned regardless of its name. ```cpp xml_attribute* last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; ```