eine kleine C++14 Async TCP/UDP/RPC/DDS-Bibliothek basierend auf asio und rpc_core
git clone --recurse-submodules [email protected]:shuai132/asio_net.git
oder
git clone [email protected]:shuai132/asio_net.git && cd asio_net
git submodule update --init --recursive
Im Folgenden finden Sie Beispiele für die Verwendung der einzelnen Module. Vollständige Unit-Tests finden Sie im Quellcode: test
RPC basiert auf TCP und RPC_Core und unterstützt auch IPv6 und SSL. Weitere Informationen finden Sie im Code rpc.cpp
// server
asio::io_context context;
rpc_server server (context, PORT /* , rpc_config */ );
server.on_session = []( const std::weak_ptr<rpc_session>& rs) {
auto session = rs. lock ();
session-> on_close = [] {};
session-> rpc -> subscribe ( " cmd " , []( const std::string& data) -> std::string {
return " world " ;
});
};
server.start( true );
// client
asio::io_context context;
rpc_client client (context /* , rpc_config */ );
client.on_open = []( const std::shared_ptr<rpc_core::rpc>& rpc) {
rpc-> cmd ( " cmd " )
-> msg ( std::string ( " hello " ))
-> rsp ([]( const std::string& data) {
assert (data == " world " );
})
-> call ();
};
client.on_close = [] {};
client.open( " localhost " , PORT);
client.run();
und Sie können zuerst rpc erstellen, für weitere Details: rpc_config.cpp
// server
auto rpc = rpc_core::rpc::create();
rpc-> subscribe ( " cmd " , []( const std::string& data) -> std::string {
assert (data == " hello " );
return " world " ;
});
asio::io_context context;
rpc_server server (context, PORT, rpc_config{. rpc = rpc});
server.start( true );
// client
auto rpc = rpc_core::rpc::create();
asio::io_context context;
rpc_client client (context, rpc_config{. rpc = rpc});
client.open( " localhost " , PORT);
client.run();
rpc-> cmd ( " cmd " )->msg(std::string( " hello " ))->call();
und Sie können C++20-Coroutine verwenden:
// server
rpc-> subscribe ( " cmd " , [&](request_response<std::string, std::string> rr) -> asio::awaitable<void> {
assert (rr-> req == " hello " );
asio::steady_timer timer (context);
timer. expires_after ( std::chrono::seconds ( 1 ));
co_await timer. async_wait ();
rr-> rsp ( " world " );
}, scheduler_asio_coroutine);
// client
// use C++20 co_await with asio, or you can use custom async implementation, and co_await it!
auto rsp = co_await rpc-> cmd ( " cmd " )->msg(std::string( " hello " ))->async_call<std::string>();
assert (rsp.data == " world " );
Überprüfen Sie den Code auf weitere Details: rpc_s_coroutine.cpp und rpc_c_coroutine.cpp
// run a server as daemon
asio::io_context context;
dds_server server (context, PORT);
server.start( true );
// client
asio::io_context context;
dds_client client (context);
client.open( " localhost " , PORT);
client.subscribe( " topic " , []( const std::string& data) {
});
client.publish<std::string>( " topic " , " string/binary " );
client.run();
// receiver
asio::io_context context;
server_discovery::receiver receiver (context, []( const std::string& name, const std::string& message) {
printf ( " receive: name: %s, message: %s n " , name. c_str (), message. c_str ());
});
context.run();
// sender
asio::io_context context;
server_discovery::sender sender_ip (context, " ip " , " message " );
context.run();
Sie können die automatische Behandlung der Paketfragmentierung mit tcp_config
aktivieren. Beim anschließenden Senden und Empfangen handelt es sich um vollständige Datenpakete.
Standardmäßig ist diese Funktion deaktiviert.
// echo server
asio::io_context context;
tcp_server server (context, PORT /* , tcp_config */ );
server.on_session = []( const std::weak_ptr<tcp_session>& ws) {
auto session = ws. lock ();
session-> on_close = [] {
};
session-> on_data = [ws](std::string data) {
ws. lock ()-> send ( std::move (data));
};
};
server.start( true );
// echo client
asio::io_context context;
tcp_client client (context /* , tcp_config */ );
client.on_data = []( const std::string& data) {
};
client.on_close = [] {
};
client.open( " localhost " , PORT);
client.run();
// server
asio::io_context context;
udp_server server (context, PORT);
server.on_data = []( uint8_t * data, size_t size, const udp::endpoint& from) {
};
server.start();
// client
asio::io_context context;
udp_client client (context);
auto endpoint = udp::endpoint(asio::ip::address_v4::from_string( " 127.0.0.1 " ), PORT);
client.send_to( " hello " , endpoint);
context.run();
asio::io_context context;
serial_port serial (context);
serial.on_open = [&] {
// / set_option
serial. set_option ( asio::serial_port::baud_rate ( 115200 ));
serial. set_option ( asio::serial_port::flow_control (asio::serial_port::flow_control::none));
serial. set_option ( asio::serial_port::parity (asio::serial_port::parity::none));
serial. set_option ( asio::serial_port::stop_bits (asio::serial_port::stop_bits::one));
serial. set_option ( asio::serial_port::character_size ( asio::serial_port::character_size ( 8 )));
// / test
serial. send ( " hello world " );
};
serial.on_data = []( const std::string& data) {
};
serial.on_open_failed = [](std::error_code ec) {
};
serial.on_close = [] {
};
serial.open( " /dev/tty.usbserial-xx " );
serial.run();
Die meisten MCUs unterstützen ASIO nicht. Es gibt eine Bibliothek, die einfach portiert werden kann: esp_rpc