io_service
. read(stream, buffer [, extra options]) async_read(stream, buffer [, extra options], handler) write(stream, buffer [, extra options]) async_write(stream, buffer [, extra options], handler)
__USE_232_SOCKETS
defined)read_until()
or async_read_until()
, which accept the boost::regex
parameter#include <boost/asio/impl/src.hpp>
(if you use SSL, then #include <boost/asio/ssl/impl/src.hpp>
)#define BOOST_ASIO_SEPARATE_COMPILATION
in all of your source files bjam –with-system –with-regex stage
bjam –with-system –with-thread –with-date_time –with-regex –withserialization stage
BOOST_ASIO_DISABLE_THREADS
, if installed; it disables support for threads in Boost. Asio, regardless of whether Boost was compiled with support for threads.callback
function that will be called by the API with the result of the operation when the operation is completed. For programmers who have extensive experience with QT - Nokia’s cross-platform library for creating graphical user interface applications, this is second nature. Thus, in asynchronous programming, you do not need to have more than one stream. using boost::asio; io_service service; ip::tcp::endpoint ep( ip::address::from_string("127.0.0.1"), 2001); ip::tcp::socket sock(service); sock.connect(ep);
io_service
. Boost.Asio uses io_service
to communicate with the operating system I / O service. Usually one instance of io_service
is enough. Next, create the address and port to which you want to connect. Create a socket. Connect the socket to your address and port: //Here is a simple synchronous server:using boost::asio; typedef boost::shared_ptr<ip::tcp::socket> socket_ptr; io_service service; ip::tcp::endpoint ep( ip::tcp::v4(), 2001)); // listen on 2001 ip::tcp::acceptor acc(service, ep); while ( true) { socket_ptr sock(new ip::tcp::socket(service)); acc.accept(*sock); boost::thread( boost::bind(client_session, sock)); } void client_session(socket_ptr sock) { while ( true) { char data[512]; size_t len = sock->read_some(buffer(data)); if ( len > 0) write(*sock, buffer("ok", 2)); } }
io_service
. Then you specify the listening port and create an acceptor (receiver) - one object that accepts client connections.client_session
function client_session
you listen to client requests, interpret them, and respond. using boost::asio; io_service service; ip::tcp::endpoint ep( ip::address::from_string("127.0.0.1"), 2001); ip::tcp::socket sock(service); sock.async_connect(ep, connect_handler); service.run(); void connect_handler(const boost::system::error_code & ec) { // here we know we connected successfully // if ec indicates success }
io_service
instance. You specify where the socket is connected and created. Then, as soon as the connection is established, you connect asynchronously to the address and port (this is the completion of the handler), that is, connect_handler
is called.connect_handler
check the error code ( ec
), and if successful, you can write to the server asynchronously.service.run()
loop will be executed as long as there are incomplete asynchronous operations. In the previous example, there is only one such operation, this is the socket async_connect
. After this, service.run()
terminates. using boost::asio; typedef boost::shared_ptr<ip::tcp::socket> socket_ptr; io_service service; ip::tcp::endpoint ep( ip::tcp::v4(), 2001)); // listen on 2001 ip::tcp::acceptor acc(service, ep); socket_ptr sock(new ip::tcp::socket(service)); start_accept(sock); service.run(); void start_accept(socket_ptr sock) { acc.async_accept(*sock, boost::bind( handle_accept, sock, _1) ); } void handle_accept(socket_ptr sock, const boost::system::error_code & err) { if ( err) return; // at this point, you can read/write to the socket socket_ptr sock(new ip::tcp::socket(service)); start_accept(sock); }
io_service
. Then you specify the port to listen on. Then you create an acceptor — an object for accepting client connections, as well as creating a dummy socket and asynchronously waiting for a client connection.service.run()
loop. When the client connects, handle_accept
is handle_accept
(the final handler for calling async_accept
). If there are no errors, then you can use this socket for read / write operations.start_accept()
again, which adds a similar asynchronous operation “waiting for client connection”, leaving the service.run()
loop busy.boost::system::system_error
. using boost::asio; ip::tcp::endpoint ep; ip::tcp::socket sock(service); sock.connect(ep); // Line 1 boost::system::error_code err; sock.connect(ep, err); // Line 2
sock.connect(ep)
threw an exception in case of an error and sock.connect(ep, err)
would return an error code. try { sock.connect(ep); } catch(boost::system::system_error e) { std::cout << e.code() << std::endl; }
boost::system::error_code err; sock.connect(ep, err); if ( err) std::cout << err << std::endl;
try {} catch
block. void client_session(socket_ptr sock) { try { ... } catch ( boost::system::system_error e) { // handle the error } }
char data[512]; boost::system::error_code error; size_t length = sock.read_some(buffer(data), error); if (error == error::eof) return; // Connection closed
boost::asio::error
(in case you want to do a full brute force search for a fault). You can also check boost/asio/error.hpp
for more details.io_service
: The io_service
class is thread safe. Multiple threads can call io_service::run()
. Most often, you probably call io_service::run()
from one thread, so the function waits until all blocking asynchronous functions are executed. However, you can call io_service::run()
from multiple threads. This blocks all threads that will call io_service::run()
. All callback functions will be called in context of all threads that called io_service::run()
; it also means that if you called io_service::run()
, only in one thread, then all callback functions will be called in the context of this thread.socket
: socket
classes are not thread safe. Thus, you should avoid situations like reading from a socket in one thread and writing to it in another (this is recommended generally, not to mention Boost.Asio).utility
: utility
classes usually do not make sense to use in multiple threads, they are not thread safe. Most of them are used for a short time and then go out of scope.io_service::run()
called from.SIGTERM
(end the program), SIGINT
(signal interruption), SIGSEGV (segment violation) and others.signal_set
and specify which signals to wait asynchronously and when one of them happens, your asynchronous handler will be called: void signal_handler(const boost::system::error_code & err, int signal) { // log this, and terminate application } boost::asio::signal_set sig(service, SIGINT, SIGTERM); sig.async_wait(signal_handler);
SIGINT
generated, you will be signal_handler
. io_service service; serial_port sp(service, "COM7");
serial_port::baud_rate rate(9600); sp.set_option(rate);
read()
, async_read()
, write()
, async_write()
, as shown in following example: char data[512]; read(sp, buffer(data, 512));
read()
, asyn_read()
and others, as shown below: HANDLE h = ::OpenFile(...); windows::stream_handle sh(service, h); char data[512]; read(h, buffer(data, 512));
posix::stream_descriptor sd_in(service, ::dup(STDIN_FILENO)); char data[512]; read(sd_in, buffer(data, 512));
bool read = false; void deadline_handler(const boost::system::error_code &) { std::cout << (read ? "read successfully" : "read failed") << std::endl; } void read_handler(const boost::system::error_code &) { read = true; } ip::tcp::socket sock(service); … read = false; char data[512]; sock.async_read_some(buffer(data, 512)); deadline_timer t(service, boost::posix_time::milliseconds(100)); t.async_wait(&deadline_handler); service.run();
read
set to true
, then our partner got to us in time. Otherwise, when deadline_handler
is called, read
is still set to false
, which means that we have not been contacted until the end of the allotted time.sleep
operation. boost::this_thread::sleep(500);
and the following fragment will do the same: deadline_timer t(service, boost::posix_time::milliseconds(500)); t.wait();
io_service
io_service
. io_service
is the most important class in the library, it deals with the operating system, waits for the end of all asynchronous operations, and then at the end it calls the handler for each such operation.io_service
instance io_service
several ways. In the following examples, we have three asynchronous operations, two connected sockets, and a wait timer:io_service
instance and one handler: io_service service_; // all the socket operations are handled by service_ ip::tcp::socket sock1(service_); // all the socket operations are handled by service_ ip::tcp::socket sock2(service_); sock1.async_connect( ep, connect_handler); sock2.async_connect( ep, connect_handler); deadline_timer t(service_, boost::posix_time::seconds(5)); t.async_wait(timeout_handler); service_.run();
io_service
instance and several handlers: io_service service_; ip::tcp::socket sock1(service_); ip::tcp::socket sock2(service_); sock1.async_connect( ep, connect_handler); sock2.async_connect( ep, connect_handler); deadline_timer t(service_, boost::posix_time::seconds(5)); t.async_wait(timeout_handler); for ( int i = 0; i < 5; ++i) boost::thread( run_service); void run_service() { service_.run(); }
io_service
instances and multiple handlers: io_service service_[2]; ip::tcp::socket sock1(service_[0]); ip::tcp::socket sock2(service_[1]); sock1.async_connect( ep, connect_handler); sock2.async_connect( ep, connect_handler); deadline_timer t(service_[0], boost::posix_time::seconds(5)); t.async_wait(timeout_handler); for ( int i = 0; i < 2; ++i) boost::thread( boost::bind(run_service, i)); void run_service(int idx) { service_[idx].run(); }
io_service
in the same thread. It makes no sense to write the following code: for ( int i = 0; i < 2; ++i) service_[i].run();
service_[1].run()
will require service_[0].run()
when you close the first one. So all asynchronous service_[1]
operations service_[1]
will have to wait for processing, which is not a good idea.connect
sock1
2 connect
sock2
, . connect
sock1
, – connect
sock2
. , sock1
1 - deadline_timer t
2, connect
sock1
. , - deadline_timer t
connect
sock1
( ), sock1
, - t
.io_service::run()
) select/epoll
; , / . , , ( 1000 ). select/epoll
.io_service::run()
) , ..run()
, , : io_service service_; tcp::socket sock(service_); sock.async_connect( ep, connect_handler); service_.run();
connect_handler
service.run()
.service.run()
, . . connect_handler
, . typedef boost::shared_ptr<io_service::work> work_ptr; work_ptr dummy_work(new io_service::work(service_));
service_.run()
until you call useservice_.stop()
or dummy_work.reset(0); // destroy dummy_work
.Source: https://habr.com/ru/post/192284/
All Articles