Boost.Asio technical documentation

Boost.Asio technical documentation

Article source: blog.csdn.net/henreash/ar...

| Boost.Asio is a cross-platform network and underlying IO C++ programming library. It uses modern C++ techniques to implement a unified asynchronous call model. head File

#include <boost/asio.hpp>
Name space ``` using namespace boost::asio;

| ------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------------------------------- | Christopher Kohlhoff Copyright 2003-2012 Christopher M. Kohlhoff Released under the software license of Boost1.0 (see attached LICENSE\_1\_0.txt file or from <http://www.boost.org/LICENSE_1_0.txt>) Boost.Asio is a cross-platform C++ library for network and low-level IO programming, providing developers with a stable asynchronous model in the C++ environment. ## []()Overview ### []()Fundamental There are many ways for applications to interact with the outside world, through files, networks, serial ports or consoles. For example, in network communication, it takes a long time to complete independent IO operations. This poses a challenge to application developers. Boost.Asio provides tools to manage long-running operations, but does not have to involve thread concurrency mode and explicit locking. The Boost.Asio library is implemented in C++ and provides common operating system interfaces such as network programming. Boost.Asio achieves the following goals: **Portability.** The library supports a series of common system operations and has stable cross-platform features. **Scalability.** The library can help developers build thousands of concurrently connected network applications. Each system operation implemented by the asio library uses the most scalable mechanism. **Efficiency.** The library supports technologies such as scatter-gather I/O (scatter-gather I/O) to make the application copy as little data as possible. **You can build model concepts through API functions like BSD Sockets. ** BSD Socket API is widely used and has many related libraries. Other programming languages usually use their simple network API interfaces. For these reasons, Boost. Asio also uses this existing technology to build. **Ease of use.** The library provides a toolbox instead of a framework to lower the entry barrier for novices. Use the least time investment to learn the basic rules and guidelines. Then, the user of the library only needs to understand the specific used Function. **Based on more abstractions. The Basis for further abstraction.asio** library provides high-level abstractions to allow other developers to extend the library. For example, to implement the commonly used HTTP protocol. Although Boost.Asio was initially positioned for network communication, the concept of asynchronous IO has been extended to the IO operations of other operating systems such as serial communication, file descriptors, and so on. ### []()Core concepts and functions #### []()Analyze Boost.Asio Boost.Asio can be used for synchronous or asynchronous operations of IO objects such as sockets. Before using Boost.Asio, first understand the concept of Boost.Asio and how to integrate with the application. The first example, look at the handling of socket connections. 1. start with the synchronization operation. ![](https://img-my.csdn.net/uploads/201204/17/1334647337_8178.JPG) The **application** must have an **io_service** object. The **io_service** object is responsible for connecting the application to the IO service of the operating system. boost::asio::io_service io_service; To perform IO operations, an application needs an IO object like TCP Socket: boost::asio::ip::tcp::socket socket(io_service); Then perform a synchronous connection operation and send the following events: 1. **Application** calls the initial connection operation of the IO object: socket.connect(server_endpoint); 2\. The IO object makes a request to **io_service**. 3. **io_service** calls the function of the **operating system** to perform the connection operation. 4. The operating system returns the execution result to **io_service**. 5. **io_service** translates the wrong operation result into boost::system::error_code type. The error_code can be compared with a specific value or detected as a boolean value (false means no error). The result is then passed to **IO Object**. 6. If the operation fails, the IO object throws an exception of type boost::system::system_error. The code to start the operation is as follows: boost::system::error_code ec; socket.connect(server_endpoint, ec); Then the variable ec of type error_code is assigned the result value of the operation, but no exception will be thrown. For asynchronous operations, the order of events is different. ![](https://img-my.csdn.net/uploads/201204/17/1334647374\_4090.JPG) 1. **The application** calls the **IO** object for connection operations: socket.async_connect(server_endpoint, your_completion_handler); The signature of your_completion_handler function is: void your_completion_handler(const boost::system::error_code& ec); The asynchronous operations performed require strict function signatures. The legal form of each operation can be found in the reference document. 2\. The IO object requests the service of **io_service**. 3. **io_service** informs the **operating system** that it needs to start an asynchronous connection. **Timing process: (** In the case of synchronization, waiting includes connection operation time.) ![](https://img-my.csdn.net/uploads/201204/17/1334647409\_6416.JPG) 4. **Operating system** indicates that the connection operation is complete, and **io_service** obtains the operation result from the queue. 5. The **application** must call io_service::run() (or a similar member function of **io_service**) in order to receive the results. Calling io_service::run() will block the application from waiting for unfinished asynchronous operations , So you can call this function after starting the first asynchronous operation. 6.After calling io_service::run(), io_service returns an operation result, translates it into error_code, and passes it to the event handler. This is a simple graphic of Boost.Asio. More features can be obtained from the documentation, such as using Boost.Asio to perform other types of asynchronous operations. ##### []() Proactor design pattern: no thread concurrency The Boost.Asio library supports both synchronous and asynchronous operations. Asynchronous support is based on the Proactor design pattern. The advantages and disadvantages of this method compared with the synchronous operation and the Reactor method are discussed below. ##### []()Proactor and Boost.Asio Now discuss the characteristics of Proactor that does not depend on platform details. ![](https://img-my.csdn.net/uploads/201204/17/1334647449\_9350.JPG) ##### []()Proactor Design Pattern -**Asynchronous operation**: Define an asynchronous execution operation, such as Socket asynchronous read and write. -**Asynchronous operation processor**: Perform asynchronous operations, and execute the queue events in the completion event queue after the operation is completed. From a higher level, the server's stream_socket_service is an asynchronous operation processor. -**Completion event queue**: Store completion events, which will be removed from the queue by the asynchronous event signal separator. -**Completion Handle**: The function executed after the asynchronous operation is completed. This is a function object, usually created using boost::bind. -**Asynchronous event signal separator**: Block waiting for events in the completion event queue, and return the completion event to the caller after being trusted. -**Proactor**: Call the asynchronous event signal separator to remove the corresponding processing event from the queue, and allocate a completion handle for this event (such as calling a function object). This function is encapsulated in the io_service class. **Initiator**: Execute specific program code to start asynchronous operations. The initializer interacts with the asynchronous operation processor through high-level interfaces such as basic_stream_socket, and returns a server proxy of type stream_socket_service. ##### []() Implementation using Reactor On many platforms, Boost.Asio implements Proactor design patterns according to the Reactor mechanism, such as select, epoll or kqueue. Compared with Proactor, its implementation is as follows: -**Asynchronous operation processor**: Reactor uses the select, epoll or kqueue mechanism to implement. If the reactor indicates that the resources for running the operation are already in place, the processor performs the asynchronous operation and inserts the corresponding completion handle in the completion event queue. - **Completion Event Queue**: A linked list of completion handles (such as function objects). -**Asynchronous event signal separator**: Wait on the event or condition variable until the completion handle in the completion event queue is available. ##### []()Realize overlapping IO of Windows In Windows NT, 2000, and XP systems, Boost.Asio uses overlapping IO to efficiently implement the Proactor design pattern: -**Asynchronous operation processor**: It is implemented by the operating system. It is initialized by calling overlapping functions such as AcceptEx. -**Completion event queue**: It is implemented by the operating system and is associated with the completion port of IO. Each io_service instance corresponds to an IO completion port. -**Asynchronous event signal separator**: Boost.Asio removes the event and its associated completion handle from the queue. ##### []() Advantages **Portability:** Many operating systems provide native asynchronous operation IO APIs (such as overlapping IO in Windows), which is the best choice for developers to develop high-performance network applications. The ASIO library uses native as much as possible Asynchronous IO. If native support is not available, the ASIO library can use a synchronous event signal separator to implement a typical Reactor mode, such as POSIX's select(). ** Remove the coupling of multi-threaded concurrency** Applications use asynchronous methods to call long-running operations, but applications do not have to explicitly create a large number of threads for increased concurrency. The implementation strategy of one thread per connection (only synchronization is required)-too many threads will generate a large number of CPU context switches, synchronization and data movement, resulting in a decrease in system efficiency. Asynchronous operations create a minimum number of operating system threads to avoid The cost of thread context switching-CPU is a typical limited resource, and at this time, only the activated logical thread is used for event processing. ** Simple application synchronization.** The asynchronous operation completion handle can be set in an existing single-threaded environment. At this time, the developed application logic is clear, and there is no need to involve synchronization issues. ** Function combination.** Function combination refers to the realization of high-level operational functions, such as sending messages in a specific format. The realization of each function relies on multiple calls to the underlying read or write operation. For example, a protocol containing a fixed-length packet header and a variable-length packet body. The length of the packet body is specified in the packet header. Assuming that the read_message operation is implemented by two lower-level reads, the first time the packet header is received, the length is obtained, and the second time the packet body is received . If these functions are combined in an asynchronous manner, these asynchronous calls can be connected together. The completion handle of the previous operation initializes the next operation. When using, only the first operation in the encapsulation chain needs to be called, and the caller will not be aware of this High-level operations are implemented in asynchronous operation chains. In this way, new operations can be easily added to the network library, and a higher level of abstraction can be developed, such as implementing the functions and support of a specific protocol. ##### []() Disadvantages ** Abstract and complex.** Because operation initialization and completion are separated in time and space, it increases the difficulty of using asynchronous mechanisms to develop programs. Moreover, the inversion of control flow makes the application difficult to debug. ** Memory usage.** In the process of reading and writing, the buffer space must be exclusively occupied, and then the buffer becomes uncertain, and each concurrent operation requires an independent buffer. In other words, in the Reactor mode, it is not until the socket is ready to read or write Buffer space is required. #### []()Threads and Boost.Asio #### []()Thread safety It is generally safe to use independent local objects in concurrent operations, but it is not safe to use the same global object in concurrent operations. However, types such as io_service can ensure that it is safe to use the same object in concurrent operations. #### []()Thread Pool Calling the io_service::run() function in multiple threads can create a thread pool containing these threads, and the threads in it call the completion handle after the asynchronous operation is completed. It can also be achieved by calling io_service::post() Arbitrary computing tasks in the entire thread pool to achieve the same goal. Note that all threads that join the io_service pool are equal, and io_service can allocate work to them in any way. #### []()Internal thread The specific platform implementation of this library creates several internal threads to simulate asynchronous operations. At the same time, these threads are invisible to library users. These thread characteristics: * Will not directly call the user's code * Block all signals Use the following guarantees to achieve: * The asynchronous completion handle will only be called by the thread that calls io_service::run(). Therefore, it is up to the user of the library to create and manage the thread that delivers the notification. the reason: * Calling io_service::run() in a single thread, user code avoids complicated thread synchronization control. For example, ASIO library users can use a single thread to implement a well-scalable server (specific user point of view). * After the thread is started, before other application code is executed, ASIO library users need to perform some short initialization operations in the thread. For example, CoInitializeEx must be called before calling Microsoft's COM operations in the thread. * Decouple the ASIO library interface from the creation and management of threads to ensure that it can be called on platforms that do not support threads. #### []()Strands: Thread without explicit lock Strand is defined as a mechanism that calls event handlers strictly in order (such as no concurrent calls). Using Strand can synchronize code execution in multi-threaded programs without explicit locking (such as mutexes, etc.). Strand can be applied implicitly or explicitly in the following two ways: Calling io_service::run() in only one thread means that all event handles are executed under an implicit Strand, because io_service guarantees that all handles are called in run(). There is only one related asynchronous operation chain in the link (such as half-duplex HTTP), and the handle cannot be executed concurrently. It is also the case of the implicit Strand. Explicit Strand needs to create an io_service::strand instance. All event handle function objects need to be wrapped with io_service::strand::wrap(), or io_service::strand for delivery or distribution. In combined asynchronous operations, such as async_read() or async_read_until(), if the completion handle is managed by one Strand, all other intermediate handles must be managed by the same Strand. This can ensure thread-safe access to all callers and Objects shared in the combined operation (for example, async_read() in the socket, the caller can call close() to cancel the operation). This is achieved by adding a hook function to all intermediate handles, which is called from before executing the final handle Hook function defined: struct my_handler {<!-- -->   void operator()() {...} };   template\<class F> void asio_handler_invoke(F f, my_handler\*) {<!-- -->  //Do custom invocation here.  //Default implementation calls f(); } The io_service::strand::wrap() function generates a new completion handle that defines asio_handler_invoke so that Strand can manage the operation of the function object. #### []()Buffer Usually IO transfers data on a continuous memory area (buffer). This buffer can be simply thought of as something containing a pointer address and some bytes. However, in order to efficiently develop network applications, Boost.Asio supports decentralized Aggregation operation requires one or more buffers: * A scatter-read receives data and stores it in multiple buffers. *. A gather-write transfers data in multiple buffers. Therefore, an abstract concept is needed to represent the buffer collection. For this purpose, Boost.Asio defines a class (actually two classes) to represent a single buffer. It can be stored in the container passed to the scattered collection operation. In addition, the buffer can be regarded as a byte array with address and size. Boost.Asio distinguishes between modifiable memory (called mutable) and non-modifiable memory (the latter is created on a storage area with a const declaration). Two types can be defined as: Copy code

typedef std::pair<void*, std::size_t> mutable_buffer;

Copy code

typedef std::pair<const void*, std::size_t> const_buffer;

Here mutable_buffer can be converted to const_buffer, but the reverse is not true. However, Boost.Asio does not use the above definition, but defines two classes: mutable_buffer and const_buffer. The purpose is to provide an opaque contiguous memory concept: * The type conversion is the same as std::pair. That is, mutable_buffer can be converted to const_buffer, but the reverse is not true. * Can prevent buffer overflow. For a buffer instance, users can only create another buffer to represent the same memory sequence or subsequence. For more security, the ASIOI library also provides a slave array (such as boost::array or std ::vector, or std::string) to automatically calculate the buffer size mechanism. * The buffer_cast function must be explicitly called for type conversion. This is usually not necessary in the application, but it must be the case when the original memory data is passed to the underlying operating system function in the implementation of the ASIO library. Finally, multiple buffers are stored in a container and can be passed to the scattered aggregation operation. (such as [read()](<> "read") or [write()](<> "write")). The concepts of MutableBufferSequence and ConstBufferSequence are defined using containers such as std::vector, std::list, std::vector or boost::array. #### []()Streambuf and IoStream integration The class boost::asio::basic_streambuf inherits from std::basic_streambuf and associates input and output streams with one or more character array type objects, each element of which can store any value. These character array objects are internal streambuf Object, but it can be used for IO operations by directly accessing the elements in the array, such as sending or receiving in the socket: * The input sequence of streambuf can be obtained through the [data()](<> "basic_streambuf::data") member function. The return value of the function meets the requirements of ConstBufferSequence. * The output sequence of streambuf can be obtained through the [prepare()](<> "basic_streambuf::data") member function. The return value of the function meets the requirements of MutableBufferSequence. * Call the [commit()](<> "basic_streambuf::commit") member function to pass data from the output sequence of the front end to the input sequence of the back end. * Call the [consume()](<> "basic_streambuf::consume") member function to remove data from the input sequence. The streambuf constructor accepts a size_t parameter to specify the sum of the input sequence and output sequence size. For any operation, if it succeeds, increase the amount of internal data, exceeding this size limit will throw a std::length_error exception. #### []() Traverse the bytes of the buffer sequence The buffers_iterator<> class template can be used to traverse a buffer sequence like a continuous byte sequence (such as MutableBufferSequence or ConstBufferSequence). The buffers_begin() and buffers_end() helper functions are provided, which automatically infer the template parameters of the buffers_iterator<>. For example, read a row of data from the socket and store it in std::string: Copy code

boost::asio::streambuf sb;

Copy code

...

Copy code

std::size_t n = boost::asio::read_until(sock, sb,'\n');

Copy code

boost::asio::streambuf::const_buffers_type bufs = sb.data();

Copy code

std::string line(

Copy code

    boost::asio::buffers_begin(bufs),

Copy code

    boost::asio::buffers_begin(bufs) + n);

#### []()Buffer debugging Some standard library implementations, such as VC++8.0 or later, provide a feature called iterator debugging. This means that the runtime will verify whether the iterator is legal. If the application tries to use an illegal iterator, an exception will be thrown .E.g: Copy code

std::vector v(1)

Copy code

std::vector::iterator i = v.begin();

Copy code

v.clear();//invalidates iterators

Copy code

*i = 0;//assertion!

**Boost.Asio** uses this feature to implement buffer debugging. For the following code: Copy code

void dont_do_this()

Copy code

{

Copy code

std::string msg = "Hello, world!";

Copy code

boost::asio::async_write(sock, boost::asio::buffer(msg), my_handler);

Copy code

}

When calling asynchronous read or write, you need to ensure that the buffer for this operation is available when the completion handle is called. In the above example, the buffer is the std::string variable msg. The variable is on the stack and has expired before the asynchronous completion. If you are lucky The program crashes, but random errors are more likely. When buffer debugging starts, Boost.Asio will store an iterator of strings, save it until the asynchronous operation is completed, and then dereference to check the validity. In the above example, you will see one before the completion of the Boost.Asio call Assertion error. When the/_GLIBCXX_DEBUG option is defined, this feature will be automatically activated in VS8.0 and later versions and GCC. Checking requires performance costs, so buffer debugging is only enabled when debug is generated. Other compilers can be activated by defining the BOOST_ASIO_ENABLE_BUFFER_DEBUGGING option It can also be stopped explicitly via the BOOST_ASIO_DISABLE_BUFFER_DEBUGGING option. #### []() Stream, short read and short write Many IO objects in Boost.Asio are stream-based. It means: * No message boundary. The transmitted data is a continuous byte sequence. * Read and write operations may pass a small number of unneeded bytes. This is called short read or short write. To provide objects based on the stream IO operation model need to simulate the following operations: * SyncReadStream, call the member function read_some() to perform a synchronous read operation. * AsyncReadStream, call the member function async_read_some() to perform asynchronous read operations. * SyncWriteStream, call the member function write_some() to perform a synchronous write operation. * AsyncWriteStream, call the member function async_write_some() to perform asynchronous write operations. Stream-based IO objects include ip::tcp::socket, ssl::stream<>, posix::stream_descriptor, windows::stream_handle, etc. Usually the program needs to pass a specified number of bytes of data. After the operation is started, a short read or short write will occur until all data is transferred. Boost.Asio provides general functions to automatically complete these operations: read(), async_read(), write() and async_write(). #### []()Why EOF is a mistake * Stream termination will cause read, async_read, read_until or async_read_until functions to violate the convention. If you want to read N bytes, it ends early due to EOF. * EOF error can distinguish stream termination and successful reading of 0 bytes.   #### []()Reactor style operation Sometimes applications must integrate third-party libraries to implement IO operations. To this end, Boost.Asio provides a null_buffers type that can be used for read and write operations. Null_buffers will not return until the IO object is ready to perform operations. For example, the following code performs a non-blocking read operation: Copy code

ip::tcp::socket socket(my_io_service);

Copy code

...

Copy code

socket.non_blocking(true);

Copy code

...

Copy code

socket.async_read_some(null_buffers(), read_handler);

Copy code

...

Copy code

void read_handler(boost::system::error_code ec)

Copy code

{

Copy code

  if (!ec)

Copy code

  {

Copy code

    std::vector buf(socket.available());

Copy code

    socket.read_some(buffer(buf));

Copy code

  }

Copy code

}

Socket supports this operation on all platforms and is a POSIX stream-based description conformance class. #### []() Line-based transfer operation Many commonly used network protocols are line-based, that is, these protocol elements are limited by the character sequence "\r\n". For example, HTTP, SMTP and FTP. In order to facilitate the implementation of line-based protocols and other protocols that use separators, Boost .Asio includes read_until() and async_read_until() functions. The following code shows the use of async_read_until() on the HTTP server to receive the first line of HTTP requests from the client: Copy code

class http_connection

Copy code

{

Copy code

  ...

Copy code

 

Copy code

  void start()

Copy code

  {

Copy code

    boost::asio::async_read_until(socket_, data_, "\r\n",

Copy code

        boost::bind(&http_connection::handle_request_line, this, _1));

Copy code

  }

Copy code

 

Copy code

  void handle_request_line(boost::system::error_code ec)

Copy code

  {

Copy code

    if (!ec)

Copy code

    {

Copy code

      std::string method, uri, version;

Copy code

      char sp1, sp2, cr, lf;

Copy code

      std::istream is(&data_);

Copy code

      is.unsetf(std::ios_base::skipws);

Copy code

      is >> method >> sp1 >> uri >> sp2 >> version >> cr >> lf;

Copy code

      ...

Copy code

    }

Copy code

  }

Copy code

 

Copy code

  ...

Copy code

 

Copy code

  boost::asio::ip::tcp::socket socket_;

Copy code

  boost::asio::streambuf data_;

Copy code

};

The Streambuf data member is used to store the data received before the delimiter is found. It is also important to record the data after the delimiter. These redundant data retained in the streambuf will be retained for subsequent calls to read_until() or async_read_until () function to check. The separator can be a single character, a std::string or a boost::regex. The read_until() and async_read_until() functions can also receive a user-defined function as a parameter to obtain matching conditions. For example, to read data in streambuf, Stop after encountering a blank character.: Copy code

typedef boost::asio::buffers_iterator<

Copy code

    boost::asio::streambuf::const_buffers_type> iterator;

Copy code

 

Copy code

std::pair<iterator, bool>

Copy code

match_whitespace(iterator begin, iterator end)

Copy code

{

Copy code

  iterator i = begin;

Copy code

  while (i != end)

Copy code

    if (std::isspace(*i++))

Copy code

      return std::make_pair(i, true);

Copy code

  return std::make_pair(i, false);

Copy code

}

Copy code

...

Copy code

boost::asio::streambuf b;

Copy code

boost::asio::read_until(s, b, match_whitespace);

Read data from streambuf until a matching character is encountered: Copy code

class match_char

Copy code

{

Copy code

public:

Copy code

  explicit match_char(char c): c_(c) {}

Copy code

 

Copy code

  template

Copy code

  std::pair<Iterator, bool> operator()(

Copy code

      Iterator begin, Iterator end) const

Copy code

  {

Copy code

    Iterator i = begin;

Copy code

    while (i != end)

Copy code

      if (c_ == *i++)

Copy code

        return std::make_pair(i, true);

Copy code

    return std::make_pair(i, false);

Copy code

  }

Copy code

 

Copy code

private:

Copy code

  char c_;

Copy code

};

Copy code

 

Copy code

namespace boost {namespace asio {

Copy code

  template <> struct is_match_condition<match_char>

Copy code

    : public boost::true_type {};

Copy code

}}//namespace boost::asio

Copy code

...

Copy code

boost::asio::streambuf b;

Copy code

boost::asio::read_until(s, b, match_char('a'));

The is_match_condition<> type will automatically evaluate whether the return value of the function and the function object with the nested result_type type definition is true. As shown in the above example, other types of characteristics must be explicitly specified. #### []()Custom memory allocation Many asynchronous operations need to allocate objects to store state data related to the operation. For example, the implementation of Win32 needs to pass overlapping sub-objects to Win32 API functions. Fortunately, the program contains an easy-to-recognize asynchronous operation chain. A half-duplex protocol (such as HTTP service) creates a single operation chain for each client. The full-duplex protocol implementation has two parallel execution chains. The program can use this rule in Reuse memory in all asynchronous operations on the chain. Assuming that a user-defined handle object h is copied, if the implementation of the handle needs to allocate memory, there should be the following code: Copy code

void* pointer = asio_handler_allocate(size, &h);

Also release memory: Copy code

asio_handler_deallocate(pointer, size, &h);

This function implements parameter-dependent positioning and search. There is a default implementation of this function in the asio space: Copy code

void* asio_handler_allocate(size_t, ...);

Copy code

void asio_handler_deallocate(void*, size_t, ...);

Implemented::operator` `new() and ::operator` `delete() functions. The function implementation ensures that memory reallocation occurs before the related handle is called, so that asynchronous operations on the same handle can reuse memory. The custom memory allocation function can be called in any user thread that calls the library function. The implementation ensures that these asynchronous operations in the library will not concurrently call the memory allocation function for the handle. The implementation must add an appropriate memory interval to ensure that different threads The memory allocation function called has the correct memory visibility. #### []()Handle tracking To debug asynchronous programs, Boost.Asio provides handle tracking support. When the BOOST_ASIO_ENABLE_HANDLER_TRACKING definition is activated, Boost.Asio writes debugging output information to the standard error stream. The output information records the relationship between asynchronous operations and their handles. This feature is very helpful for debugging. You need to know how asynchronous operations are linked together, or what asynchronous operations are suspended. The following is the debugging information output by the HTTP service, processing a single request, and then pressing Ctrl+C to exit: Copy code

@asio|1298160085.070638|0*1| signal_set@0x7fff50528f40.async_wait

Copy code

@asio|1298160085.070888|0*2| socket@0x7fff50528f60.async_accept

Copy code

@asio|1298160085.070913|0| resolver@0x7fff50528e28.cancel

Copy code

@asio|1298160118.075438|>2|ec=asio.system:0

Copy code

@asio|1298160118.075472|2*3| socket@0xb39048.async_receive

Copy code

@asio|1298160118.075507|2*4| socket@0x7fff50528f60.async_accept

Copy code

@asio|1298160118.075527|<2|

Copy code

@asio|1298160118.075540|>3|ec=asio.system:0,bytes_transferred=122

Copy code

@asio|1298160118.075731|3*5| socket@0xb39048.async_send

Copy code

@asio|1298160118.075778|<3|

Copy code

@asio|1298160118.075793|>5|ec=asio.system:0,bytes_transferred=156

Copy code

@asio|1298160118.075831|5| socket@0xb39048.close

Copy code

@asio|1298160118.075855|<5|

Copy code

@asio|1298160122.827317|>1|ec=asio.system:0,signal_number=2

Copy code

@asio|1298160122.827333|1| socket@0x7fff50528f60.close

Copy code

@asio|1298160122.827359|<1|

Copy code

@asio|1298160122.827370|>4|ec=asio.system:125

Copy code

@asio|1298160122.827378|<4|

Copy code

@asio|1298160122.827394|0| signal_set@0x7fff50528f40.cancel

The format of each line is: Copy code

|||

\<tag> has always been @asio, used to identify and extract handle tracking messages in the program output. `<timestamp>` is the number of seconds since January 1, 1970 UTC time. `<action>` has the following forms: **>n** The program entered the nth handle./<description> describes the handle parameters. **\<n** The program exits the nth handle. **!n** The program exited the nth handle due to an exception. **\~n** The nth handle is destroyed without being executed. It is usually because the asynchronous operation has not been completed when the io_service is destroyed. **n\*m** The nth handle creates a new asynchronous operation that generates the mth completion handle./<description> describes what asynchronous operation is started. **n** The nth handle performs other operations./<description> shows which functions are called. Usually only close() and cancel() operations are recorded because they affect the pending state of asynchronous operations. When/<description> shows synchronous or asynchronous operation, the format is `<object-type>@<pointer>.<operation>`. The parameters and values of the execution handle are displayed in comma intervals. As shown above, each handle is identified by a unique number. The handle number of the handle tracking output is 0, which means that the operation is not performed by these handles. #### []()Visualization Handle trace output can be processed using the tools included in `handlerviz.pl` to create a visual interface. ### []()The internet #### []()TCP,UDP and ICMP Boost.Asio provides complete support for TCP, UDP and ICMP. ##### []()TCP client Use resolver to perform host name resolution, query host and service names and convert them to one or more endpoints: Copy code

ip::tcp::resolver resolver(my_io_service);

Copy code

ip::tcp::resolver::query query(" www.boost.org ", "http");

Copy code

ip::tcp::resolver::iterator iter = resolver.resolve(query);

Copy code

ip::tcp::resolver::iterator end;//End marker.

Copy code

while (iter != end)

Copy code

{

Copy code

  ip::tcp::endpoint endpoint = *iter++;

Copy code

  std::cout << endpoint << std::endl;

Copy code

}

The endpoints included in the above list can be IPv4 and IPv6 endpoints, so the program needs to try each case until it gets an available endpoint. This makes the program independent of a specific IP version. In order to develop a program independent of the protocol, the TCP client can use the [connect()](<> "connect") and [async_connect()](<> "async_connect") functions to establish a connection. This operation will try every Endpoints until the Socket connection is successful. For example, a simple call: Copy code

ip::tcp::socket socket(my_io_service);

Copy code

boost::asio::connect(socket, resolver.resolve(query));

All endpoints will be tried at the same time until a successful connection is found. The same asynchronous operation method is: Copy code

boost::asio::async_connect(socket_, iter,

Copy code

    boost::bind(&client::handle_connect, this,

Copy code

      boost::asio::placeholders::error));

Copy code

 

Copy code

//...

Copy code

 

Copy code

void handle_connect(const error_code& error)

Copy code

{

Copy code

  if (!error)

Copy code

  {

Copy code

   //Start read or write operations.

Copy code

  }

Copy code

  else

Copy code

  {

Copy code

   //Handle error.

Copy code

  }

Copy code

}

When a specific endpoint is available, the socket is created and connected. The method is: Copy code

ip::tcp::socket socket(my_io_service);

Copy code

socket.connect(endpoint);

Use member functions [receive()](<> "basic_stream_socket::receive"),[async_receive()](<> "basic_stream_socket::async_receive"),[send()](<> "basic_stream_socket::send") Or [async_send()](<> "basic_stream_socket::async_send") can read or write data to the TCP connection socket. However, for fast read and write operations, usually use [read()](<> "read "),[async_read()](<> "async_read"),[write()](<> "write") and [async_write()](<> "async_write") functions to operate. ##### []()TCP service The program uses the receiver to receive the TCP connection that arrives: Copy code

ip::tcp::acceptor acceptor(my_io_service, my_endpoint);

Copy code

...

Copy code

ip::tcp::socket socket(my_io_service);

Copy code

acceptor.accept(socket);

When a socket connection is successfully received (to the TCP client in the above example), you can read or write data on it. ##### []()UDP UDP also uses resolver to resolve host names: Copy code

ip::udp::resolver resolver(my_io_service);

Copy code

ip::udp::resolver::query query("localhost", "daytime");

Copy code

ip::udp::resolver::iterator iter = resolver.resolve(query);

Copy code

...

UDP is bound to the local endpoint. The following code creates an IPv4 UDP Socket and binds it to port 12345 of any address: Copy code

ip::udp::endpoint endpoint(ip::udp::v4(), 12345);

Copy code

ip::udp::socket socket(my_io_service, endpoint);

Use member functions [receive_from()](<> "basic_datagram_socket::receive_from"),[async_receive_from()](<> "basic_datagram_socket::async_receive_from"),[send_to()](<> "basic_datagram_socket)::send_tocket) Or [async_send_to()](<> "basic_datagram_socket::async_send_to") to read or write data on a connected UPD Socket. For a connected UDP Socket, you can use [receive()](<> "basic_datagram_socket: :receive"),[async_receive()](<> "basic_datagram_socket::async_receive"),[send()](<> "basic_datagram_socket::send") or [async_send()](<> "basic_datagram_socket::async_send ") member function. ##### []()ICMP Like TCP and UPD, ICMP also uses resolver to resolve host names: Copy code

ip::icmp::resolver resolver(my_io_service);

Copy code

ip::icmp::resolver::query query("localhost", "");

Copy code

ip::icmp::resolver::iterator iter = resolver.resolve(query);

Copy code

...

ICMP Socket may be bound to a local endpoint. The following code creates an IPv6 version of ICMP Socket and binds it to an arbitrary address: Copy code

ip::icmp::endpoint endpoint(ip::icmp::v6(), 0);

Copy code

ip::icmp::socket socket(my_io_service, endpoint);

ICMP does not have to specify the port number. Use member functions [receive_from()](<> "basic_raw_socket::receive_from"),[async_receive_from()](<> "basic_raw_socket::async_receive_from"),[send_to()](<> "basic_raw_socket::send_to") Or [async_send_to()](<> "basic_raw_socket::async_send_to") to read or write data on the connectionless ICMP. ##### []()Other agreements Support for other Socket protocols (such as Bluetooth or IRCOMM) can be implemented as required by the protocol. #### []()Socket IO stream Boost.Asio contains an iostream class implemented on Socket. It hides the implementation of complex features such as endpoint resolution and protocol independence. To create a connection, you only need to write a few lines of code: Copy code

ip::tcp::iostream stream(" www.boost.org ", "http");

Copy code

if (!stream)

Copy code

{

Copy code

 //Can't connect.

Copy code

}

The iostream class can create a simple server together with the receiver. For example: Copy code

io_service ios;

Copy code

 

Copy code

ip::tcp::endpoint endpoint(tcp::v4(), 80);

Copy code

ip::tcp::acceptor acceptor(ios, endpoint);

Copy code

 

Copy code

for (;;)

Copy code

{

Copy code

  ip::tcp::iostream stream;

Copy code

  acceptor.accept(*stream.rdbuf());

Copy code

  ...

Copy code

}

The expires_at() or expires_from_now() functions can be used to set the timeout period. Socket operations that time out will set the iostream to the "bad" state. For example, a simple client program: Copy code

ip::tcp::iostream stream;

Copy code

stream.expires_from_now(boost::posix_time::seconds(60));

Copy code

stream.connect(" www.boost.org ", "http");

Copy code

stream << "GET/LICENSE_1_0.txt HTTP/1.0\r\n";

Copy code

stream << "Host: www.boost.org\r\n ";

Copy code

stream << "Accept: //r\n";

Copy code

stream << "Connection: close\r\n\r\n";

Copy code

stream.flush();

Copy code

std::cout << stream.rdbuf();

If the total time of all Socket operations exceeds 60 seconds, it will fail. If an error occurs, you can use the error() member function of iostream to obtain the error code of the most recent system operation: Copy code

if (!stream)

Copy code

{

Copy code

  std::cout << "Error: "<< stream.error().message() << "\n";

Copy code

}

##### []()Note This iostream template only supports char and does not support wchar_t, so don't use it for such a code version. #### []()BSD Socket API and Boost.Asio Boost.Asio contains a library that implements the low-level Socket interface of the BSD Socket API. The latter is also used as the most basic network API in other languages, such as Java. The bottom-level interface can be used to develop high-efficiency and high-scalability applications For example, programmers can better control the number of system calls, avoid copying basic data, and minimize the use of resources such as threads. The BSD Socket API contains insecure and error-prone aspects. For example, using integer numbers to represent the lack of security of sockets. Boost.Asio uses different Socket types to represent different protocols. For example, TCP corresponds to ip::tcp: :socket, ip::udp::socket corresponding to UDP. The following table is a comparison between BSD Socket API and Boost.Asio: | **BSD Socket API Elements** | **Boost.Asio mid-priced content**| | ------------------------------------------------- ----------------------------------------------- |-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ---------------------------------------------------- | | Socket descriptor-int (POSIX) or SOCKET (Windows) | TCP: [ip::tcp::socket](<> "ip::tcp::socket"), [ip::tcp::acceptor]( <> "ip::tcp::acceptor")UDP: [ip::udp::socket](<> "ip::udp::socket")[basic_socket](<> "basic_socket"),[basic_stream_socket] (<> "basic_stream_socket"),[basic_datagram_socket](<> "basic_datagram_socket"),[basic_raw_socket](<> "basic_raw_socket") | | in_addr, in6\_addr | [ip::address](<> "ip::address"),[ip::address_v4](<> "ip::address"),[ip::address_v6](<> "ip::address") ||| | sockaddr_in, sockaddr_in6 | TCP: [ip::tcp::endpoint](<> "ip::tcp::endpoint")UDP: [ip::udp::endpoint](<> "ip::udp:: endpoint")[ip::basic_endpoint](<> "ip::basic_endpoint") ||| | accept() | TCP: [ip::tcp::acceptor::accept()](<> "basic_socket_acceptor::accept")[basic_socket_acceptor::accept()](<> "basic_socket_acceptor::accept") ||| | bind() | TCP: [ip::tcp::acceptor::bind()](<> "basic_socket::bind"), [ip::tcp::socket::bind()](<> " basic_socket::bind")UDP: [ip::udp::socket::bind()](<> "basic_socket::bind")[basic_socket::bind()](<> "basic_socket::bind") ||| | close() | TCP: [ip::tcp::acceptor::close()](<> "basic_socket::close"), [ip::tcp::socket::close()](<> " basic_socket::close")UDP: [ip::udp::socket::close()](<> "basic_socket::close")[basic_socket::close()](<> "basic_socket::close") ||| | connect() | TCP: [ip::tcp::socket::connect()](<> "basic_socket::connect")UDP: [ip::udp::socket::connect()](<> "basic_socket::connect")[basic_socket::connect()](<> "basic_socket::connect") ||| | getaddrinfo(), gethostbyaddr(), gethostbyname(), getnameinfo(), getservbyname(), getservbyport() | TCP: [ip::tcp::resolver::resolve()](<> "ip::basic_resolver: :resolve"), [ip::tcp::resolver::async_resolve()](<> "ip::basic_resolver::async_resolve")UDP: [ip::udp::resolver::resolve()](< > "ip::basic_resolver::resolve"), [ip::udp::resolver::async_resolve()](<> "ip::basic_resolver::async_resolve")[ip::basic_resolver::resolve()] (<> "ip::basic_resolver::resolve"),[ip::basic_resolver::async_resolve()](<> "ip::basic_resolver::async_resolve") | | gethostname() | [ip::host_name()](<> "ip::host_name")| | getpeername() | TCP: [ip::tcp::socket::remote_endpoint()](<> "basic_socket::remote_endpoint")UDP: [ip::udp::socket::remote_endpoint()](<> "basic_socket::remote_endpoint")[basic_socket::remote_endpoint()](<> "basic_socket::remote_endpoint") ||| | getsockname() | TCP: [ip::tcp::acceptor::local_endpoint()](<> "basic_socket::local_endpoint"), [ip::tcp::socket::local_endpoint()](<> " basic_socket::local_endpoint")UDP: [ip::udp::socket::local_endpoint()](<> "basic_socket::local_endpoint")[basic_socket::local_endpoint()](<> "basic_socket::local_endpoint") | | getsockopt() | TCP: [ip::tcp::acceptor::get_option()](<> "basic_socket::get_option"), [ip::tcp::socket::get_option()](<> " basic_socket::get_option")UDP: [ip::udp::socket::get_option()](<> "basic_socket::get_option")[basic_socket::get_option()](<> "basic_socket::get_option") | | inet_addr(), inet_aton(), inet_pton() | [ip::address::from_string()](<> "ip::address::from_string"),[ip::address_v4::from_string()]( <> "ip::address::from_string"),[ip_address_v6::from_string()](<> "ip::address::from_string") ||| | inet_ntoa(), inet_ntop() | [ip::address::to_string()](<> "ip::address::to_string"),[ip::address_v4::to_string()](<> "ip ::address::to_string"),[ip_address_v6::to_string()](<> "ip::address::to_string") ||| | ioctl() | TCP: [ip::tcp::socket::io_control()](<> "basic_socket::io_control")UDP: [ip::udp::socket::io_control()](<> "basic_socket::io_control")[basic_socket::io_control()](<> "basic_socket::io_control") ||| | listen() | TCP: [ip::tcp::acceptor::listen()](<> "basic_socket_acceptor::listen")[basic_socket_acceptor::listen()](<> "basic_socket_acceptor::listen") ||| | poll(), select(), pselect() | [io_service::run()](<> "io_service::run"),[io_service::run_one()](<> "io_service::run_one") ,[io_service::poll()](<> "io_service::poll"),[io_service::poll_one()](<> "io_service::poll_one") Note: Including asynchronous operations.||| | readv(), recv(), read() | CP: [ip::tcp::socket::read_some()](<> "basic_stream_socket::read_some"), [ip::tcp::socket:: async_read_some()](<> "basic_stream_socket::async_read_some"), [ip::tcp::socket::receive()](<> "basic_stream_socket::receive"), [ip::tcp::socket:: async_receive()](<> "basic_stream_socket::async_receive")UDP: [ip::udp::socket::receive()](<> "basic_datagram_socket::receive"), [ip::udp::socket: :async_receive()](<> "basic_datagram_socket::async_receive")[basic_stream_socket::read_some()](<> "basic_stream_socket::read_some"),[basic_stream_socket::async_read_some()](<> "basic:async_readcket()](<> "basic:async_readcket "),[basic_stream_socket::receive()](<> "basic_stream_socket::receive"),[basic_stream_socket::async_receive()](<> "basic_stream_socket::async_receive"),[basic_datagram_socket::receive()](<> "basic_datagram_socket::receive "),[basic_datagram_socket::async_receive()](<> "basic_datagram_socket::async_receive") | | recvfrom() | UDP: [ip::udp::socket::receive_from()](<> "basic_datagram_socket::receive_from"), [ip::udp::socket::async_receive_from()](<> " basic_datagram_socket::async_receive_from")[basic_datagram_socket::receive_from()](<> "basic_datagram_socket::receive_from"),[basic_datagram_socket::async_receive_from()](<> "basic_datagram" from) | | send(), write(), writev() | TCP: [ip::tcp::socket::write_some()](<> "basic_stream_socket::write_some"), [ip::tcp::socket:: async_write_some()](<> "basic_stream_socket::async_write_some"), [ip::tcp::socket::send()](<> "basic_stream_socket::send"), [ip::tcp::socket:: async_send()](<> "basic_stream_socket::async_send")UDP: [ip::udp::socket::send()](<> "basic_datagram_socket::send"), [ip::udp::socket: :async_send()](<> "basic_datagram_socket::async_send")[basic_stream_socket::write_some()](<> "basic_stream_socket::write_some"),[basic_stream_socket::async_write_some()](<> "basic_async_socket: "),[basic_stream_socket::send()](<> "basic_stream_socket::send"),[basic_stream_socket::async_send()](<> "basic_stream_socket::async_send"),[basic_datagram_socket::send()](<> "basic_datagram_socket::send")_send: ()](<> "basic_datagram_socket::async_send") | | sendto() | UDP: [ip::udp::socket::send_to()](<> "basic_datagram_socket::send_to"), [ip::udp::socket::async_send_to()](<> " basic_datagram_socket::async_send_to")[basic_datagram_socket::send_to()](<> "basic_datagram_socket::send_to"),[basic_datagram_socket::async_send_to()](<> "basic_datagram_socket::"async_send_to") | | setsockopt() | TCP: [ip::tcp::acceptor::set_option()](<> "basic_socket::set_option"), [ip::tcp::socket::set_option()](<> " basic_socket::set_option")UDP: [ip::udp::socket::set_option()](<> "basic_socket::set_option")[basic_socket::set_option()](<> "basic_socket::set_option") | | shutdown() | TCP: [ip::tcp::socket::shutdown()](<> "basic_socket::shutdown")UDP: [ip::udp::socket::shutdown()](<> "basic_socket::shutdown")[basic_socket::shutdown()](<> "basic_socket::shutdown") ||| | sockatmark() | TCP: [ip::tcp::socket::at_mark()](<> "basic_socket::at_mark")[basic_socket::at_mark()](<> "basic_socket::at_mark") ||| | socket() | TCP: [ip::tcp::acceptor::open()](<> "basic_socket::open"), [ip::tcp::socket::open()](<> " basic_socket::open")UDP: [ip::udp::socket::open()](<> "basic_socket::open")[basic_socket::open()](<> "basic_socket::open") ||| | socketpair() | [local::connect_pair()](<> "local::connect_pair") Note: Only suitable for POSIX operating system.||| ### []()Timer Long-running operations usually set a final completion deadline. This deadline can be expressed in absolute time, but relative time is usually used. A simple example to perform awaiting asynchronous operations in relative time: Copy code

io_service i;

Copy code

...

Copy code

deadline_timer t(i);

Copy code

t.expires_from_now(boost::posix_time::seconds(5));

Copy code

t.wait();

Usually, the program will perform an asynchronous wait operation based on a timer: Copy code

void handler(boost::system::error_code ec) {...}

Copy code

...

Copy code

io_service i;

Copy code

...

Copy code

deadline_timer t(i);

Copy code

t.expires_from_now(boost::posix_time::milliseconds(400));

Copy code

t.async_wait(handler);

Copy code

...

Copy code

i.run();

The timeout period associated with the timer can be a relative time: Copy code

boost::posix_time::time_duration time_until_expiry

Copy code

  = t.expires_from_now();

Or use absolute time: Copy code

deadline_timer t2(i);

Copy code

t2.expires_at(t.expires_at() + boost::posix_time::seconds(30));

### []()Serial port Boost.Asio contains classes for creating and operating serial ports in a flexible way. For example, the code to open the serial port: Copy code

serial_port port(my_io_service, name);

The name is "COM1" in Windows, and "/dev/ttyS0" in POSIX platform. After opening, the serial port can be used like a stream. This object can be used in [async_read()](<> "async_read"),[write()](<> "write"),[async_write()]( <> "async_write"),[read_until()](<> "read_until") or [async_read_until()](<> "async_read_until") function. The serial port implementation also includes optional classes such as configuring the serial port baud rate, flow control, parity, stop bits, and the number of characters. #### []()Note The serial port can be used on all POSIX platforms. The serial port communication in Windows needs to activate the IO completion port during compilation. The program can test the BOOST_ASIO_HAS_SERIAL_PORTS macro to check whether the Windows system supports serial port operation. ### []()Signal processing Boost.Asio implements signal processing through the signal_set class. The program can add one or more signals to the collection, and then perform the asyn_wait() operation. When one of the signals occurs, a specific event processing function is executed. The same signal can be registered in multiple singal_set object, but these signals can only be used in Boost.Asio. Copy code

void handler(

Copy code

    const boost::system::error_code& error,

Copy code

    int signal_number)

Copy code

{

Copy code

  if (!error)

Copy code

  {

Copy code

   //A signal occurred.

Copy code

  }

Copy code

}

Copy code

 

Copy code

...

Copy code

 

Copy code

//Construct a signal set registered for process termination.

Copy code

boost::asio::signal_set signals(io_service, SIGINT, SIGTERM);

Copy code

 

Copy code

//Start an asynchronous wait for one of the signals to occur.

Copy code

signals.async_wait(handler);

Signal processing can also be used in Windows, which is equivalent to events mapped to the console by the VC++ runtime library, such as Ctrl+C. ### []()POSIX-specific functions #### []()Socket in UNIX Boost.Asio provides basic support for Socket in the UNIX field (also known as local Socket). The simplest use case is to have a pair of connected Sockets. The code is as follows: Copy code

local::stream_protocol::socket socket1(my_io_service);

Copy code

local::stream_protocol::socket socket2(my_io_service);

Copy code

local::connect_pair(socket1, socket2);

A pair of stream-based sockets will be created. To implement a packet-based socket, use: Copy code

local::datagram_protocol::socket socket1(my_io_service);

Copy code

local::datagram_protocol::socket socket2(my_io_service);

Copy code

local::connect_pair(socket1, socket2);

Socket services in the UNIX domain can be created on a receiver bound to an endpoint, and TCP services are similar: Copy code

::unlink("/tmp/foobar");//Remove previous binding.

Copy code

local::stream_protocol::endpoint ep("/tmp/foobar");

Copy code

local::stream_protocol::acceptor acceptor(my_io_service, ep);

Copy code

local::stream_protocol::socket socket(my_io_service);

Copy code

acceptor.accept(socket);

The client connects to the server code: Copy code

local::stream_protocol::endpoint ep("/tmp/foobar");

Copy code

local::stream_protocol::socket socket(my_io_service);

Copy code

socket.connect(ep);

Boost.Asio does not support the transfer of file descriptors or certificates across UNIX Sockets, but it can be achieved by using the native() function to call the underlying descriptors of the Socket. ##### []()Note Socket in the UNIX domain is only activated when compiling on a supported platform. You can test the BOOST_ASIO_HAS_LOCAL_SOCKETS macro to check whether it is supported. #### []()Stream-based file descriptor Boost.Asio contains classes for synchronous or asynchronous reading and writing on POSIX file descriptors, such as pipes, standard input and output, and various devices (but not regular files). For example, to perform read and write on standard input and output, create the following objects: Copy code

posix::stream_descriptor in(my_io_service, ::dup(STDIN_FILENO));

Copy code

posix::stream_descriptor out(my_io_service, ::dup(STDOUT_FILENO));

Then the stream is read and written synchronously or asynchronously. That is, the object can be used in [read()](<> "read"),[async_read()](<> "async_read"),[write()](<> "write" ),[async_write()](<> "async_write"),[read_until()](<> "read_until") or [async_read_until()](<> "async_read_until") and other functions. ##### []()Note The POSIX stream descriptor is only activated when compiling on a supported platform. The program can check the BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR macro to check whether it is supported. #### []()Fork Boost.Asio supports programs using the fork() system call. Programs can call io_service.notify_fork() at an appropriate time, and Boost.Asio can recreate an internal file descriptor (such as using the "self-pipe trick" descriptor technique to activate the response (Reactor)). The notification usage is as follows: Copy code

io_service_.notify_fork(boost::asio::io_service::fork_prepare);

Copy code

if (fork() == 0)

Copy code

{

Copy code

  io_service_.notify_fork(boost::asio::io_service::fork_child);

Copy code

  ...

Copy code

}

Copy code

else

Copy code

{

Copy code

  io_service_.notify_fork(boost::asio::io_service::fork_parent);

Copy code

  ...

Copy code

}

User-defined services can override the io_service::service::fork_service() virtual function to intentionally create fork operations. Note that all file descriptors accessible by Boost.Asio's public API functions (such as the descriptors under basic_socket<>, posix::stream_descriptor) will not change during the fork. This requires the program to manage as needed. ### []()Windows-specific functions #### []() Stream-oriented handle Boost.Asio contains classes that allow asynchronous read or write operations on Windows handles, such as named pipes. For example, to perform an asynchronous operation on a named pipe, create the following object: Copy code

HANDLE handle = ::CreateFile(...);

Copy code

windows::stream_handle pipe(my_io_service, handle);

Then use the synchronous or asynchronous way to read and write the stream. That is, the object can be used in [read()](<> "read"),[async_read()](<> "async_read"),[write()](<> "write "),[async_write()](<> "async_write"),[read_until()](<> "read_until") or [async_read_until()](<> "async_read_until") function. The kernel object relative to the handle must support the IO completion port (named pipes support, but anonymous pipes and console streams do not). ##### []()Note The Windows handle stream can only be activated during compilation, and only the IO completion port must be used as background processing (default). You can use the BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE macro to detect. #### []() Random access handle Boost.Asio provides specific classes to implement asynchronous read and write operations on the related handles of the rule file. For example, to execute asynchronous operation code on a file: Copy code

HANDLE handle = ::CreateFile(...);

Copy code

windows::random_access_handle file(my_io_service, handle);

You can read or write data through the member functions read_some_at(), async_read_some_at(), write_some_at() or async_write_some_at(). However, like the equivalent functions on the stream (read_some(), etc.), these functions only need to be in a single One or more bytes are passed in the operation. Therefore, [read_at()](<> "read_at"),[async_read_at()](<> "async_read_at"),[write_at()](<> "write_at" ) And [async_write_at()](<> "async_write_at") function, internally call the corresponding **\*** `_some_at()` function repeatedly until all data transfer is completed. ##### []()Note The Windows random read handle can only be activated during compile time, and it is available for processing using the IO completion port in the background. You can use the BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE macro to detect. #### []() Object handle Boost.Asio provides Windows-specific classes to implement asynchronous wait operations on kernel object handles: * Modification notice * Console input * Event * Memory resource notification * Process * signal * Thread * Waiting timer For example, to perform an asynchronous operation on an event, create the following object: Copy code

HANDLE handle = ::CreateEvent(...);

Copy code

windows::object_handle file(my_io_service, handle);

The wait() and async_wait() member functions are used to wait for the kernel object to be trusted. ##### []()Note The Windows object handle needs to be activated during compilation. You can use the BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE macro to check. ### []()[SSL](<> "SSL") Boost.Asio includes classes and class templates that support SSL. These classes can encrypt existing streams (such as TCP Socket) during communication. Before creating an encrypted stream, the application must construct an SSL context object. This object usually sets SLL options such as authentication mode, certificate file, etc. For example, the client initialization code is as follows: Copy code

ssl::context ctx(ssl::context::sslv23);

Copy code

ctx.set_verify_mode(ssl::verify_peer);

Copy code

ctx.load_verify_file("ca.pem");

Use SSL under TCP Socket: Copy code

ssl::stream ip::tcp::socket ssl_sock(my_io_service, ctx);

To perform specific Socket operations, such as establishing a remote connection or receiving a connection, the underlying Socket must use the lowest_layer() member function of the ssl::stream template to obtain: Copy code

ip::tcp::socket::lowest_layer_type& sock = ssl_sock.lowest_layer();

Copy code

sock.connect(my_endpoint);

Sometimes the lifetime of the underlying stream object is longer than the SSL stream, then the template parameter needs to refer to the stream type: Copy code

ip::tcp::socket sock(my_io_service);

Copy code

ssl::stream ip::tcp::socket& ssl_sock(sock, ctx);

The SSL encrypted connection handshake needs to be carried out before transmitting or receiving data. The connection can be established through the handshake() or async_handshake() member functions of the ssl::stream template. After connection, the SSL stream object can be used in the same way as a synchronous or asynchronous read and write stream. That is, the object can be used in [read()](<> "read"),[async_read()](<> "async_read") ,[write()](<> "write"),[async_write()](<> "async_write"),[read_until()](<> "read_until") or [async_read_until()](<> "async_read_until ")function. #### []()Certificate Verification Boost.Asio provides various methods to configure SSL certificate verification: * [ssl::context::set_default_verify_paths()](<> "ssl::context::set_default_verify_paths") * [ssl::context::set_verify_mode()](<> "ssl::context::set_verify_mode") * [ssl::context::set_verify_callback()](<> "ssl::context::set_verify_callback") * [ssl::context::load_verify_file()](<> "ssl::context::load_verify_file") * [ssl::stream::set_verify_mode()](<> "ssl::stream::set_verify_mode") * [ssl::stream::set_verify_callback()](<> "ssl::stream::set_verify_callback") In simple cases, the certificate verification rule is RFC2818 (certificate verification under HTTPS), and Boost.Asio provides a reusable certificate verification callback function object: * [ssl::rfc2818\_verification](<> "ssl::rfc2818\_verification") The following example demonstrates the use of HTTPS to verify the certificate of the remote host: Copy code

using boost::asio::ip::tcp;

Copy code

namespace ssl = boost::asio::ssl;

Copy code

typedef ssl::stream tcp::socket ssl_socket;

Copy code

 

Copy code

//Create a context that uses the default paths for

Copy code

//finding CA certificates.

Copy code

ssl::context ctx(ssl::context::sslv23);

Copy code

ctx.set_default_verify_paths();

Copy code

 

Copy code

//Open a socket and connect it to the remote host.

Copy code

boost::asio::io_service io_service;

Copy code

ssl_socket sock(io_service, ctx);

Copy code

tcp::resolver resolver(io_service);

Copy code

tcp::resolver::query query("host.name", "https");

Copy code

boost::asio::connect(sock.lowest_layer(), resolver.resolve(query));

Copy code

sock.lowest_layer().set_option(tcp::no_delay(true));

Copy code

 

Copy code

//Perform SSL handshake and verify the remote host's

Copy code

//certificate.

Copy code

sock.set_verify_mode(ssl::verify_peer);

Copy code

sock.set_verify_callback(ssl::rfc2818_verification("host.name"));

Copy code

sock.handshake(ssl_socket::client);

Copy code

 

Copy code

//... read and write as normal ...

#### []()SSL and threads SSL stream objects are executed without locking. Therefore, asynchronous execution of SSL requires implicit or explicit application strand. Note that this means that there is no need for synchronization control in a single-threaded program (locks are not necessary). #### []()Note OpenSSL requires Boost.Asio's SSL support. When an application uses OpenSSL functions that are not packaged by Boost.Asio, the underlying OpenSSL class can be used by calling [ssl::context::native_handle()](<> "ssl::context ::native_handle") or [ssl::stream::native_handle()](<> "ssl::stream::native_handle"). ### []()C++2011 support #### []() Movable IO object After C++ supports moving objects (referenced by rvalues), Boost.Asio can move the construction and assignment of sockets, serial ports, POSIX descriptors and Windows handles. The following code can be achieved by moving the object: Copy code

tcp::socket make_socket(io_service& i)

Copy code

{

Copy code

  tcp::socket s(i);

Copy code

  ...

Copy code

  std::move(s);

Copy code

}

or: Copy code

class connection: public enable_shared_from_this

Copy code

{

Copy code

private:

Copy code

  tcp::socket socket_;

Copy code

  ...

Copy code

public:

Copy code

  connection(tcp::socket&& s): socket_(std::move(s)) {}

Copy code

  ...

Copy code

};

Copy code

 

Copy code

...

Copy code

 

Copy code

class server

Copy code

{

Copy code

private:

Copy code

  tcp::acceptor acceptor_;

Copy code

  tcp::socket socket_;

Copy code

  ...

Copy code

  void handle_accept(error_code ec)

Copy code

  {

Copy code

    if (!ec)

Copy code

      std::make_shared(std::move(socket_))->go();

Copy code

    acceptor_.async_accept(socket_, ...);

Copy code

  }

Copy code

  ...

Copy code

};

Simultaneously: Copy code

std::vector tcp::socket sockets;

Copy code

sockets.push_back(tcp::socket(...));

A word of truth: when an asynchronous operation is suspended, it is possible to continue to move the object, but this is not a good idea. Especially when the operation is triggered by a function such as async_read(), it references the stream object. Moving the object during the operation will cause The corresponding operation accesses the moved object. Mobile support is automatically supported by adding `-std=c++0x` or `-std=gnu++0x` compilation option in g++4.5 and later versions. It can be disabled through the BOOST_ASIO_DISABLE_MOVE definition macro or activated by the BOOST_ASIO_HAS_MOVE macro. Note these Macros also affect movable handles. #### []()Removable handle After optimization, the user-defined completion handle can support move construction, and the implementation of Boost.Asio will take precedence over the copy constructor to use the move constructor. In the current environment, Boost.Asio may also remove the copy constructor of all handles. However, the handle type You still need a copy constructor. When mobile support is activated, the asynchronous code is: Copy code

template

Copy code

void async_XYZ(..., Handler handler);

Actually declared as: Copy code

template

Copy code

void async_XYZ(..., Handler&& handler);

The handle parameter is perfectly passed inside the async_XYZ function body, and a movement construction occurs. This ensures that all other parameters of the function will be evaluated in advance. This is especially important when the other parameters of async_XYZ() are members of the handle. For example: Copy code

struct my_operation

Copy code

{

Copy code

  shared_ptr tcp::socket socket;

Copy code

  shared_ptr<vector> buffer;

Copy code

  ...

Copy code

  void operator(error_code ec, size_t length)

Copy code

  {

Copy code

    ...

Copy code

    socket->async_read_some(boost::asio::buffer(*buffer), std::move(*this));

Copy code

    ...

Copy code

  }

Copy code

};

Mobile support is automatically supported by adding `-std=c++0x` or `-std=gnu++0x` compilation option in g++4.5 and later versions. It can be disabled through the BOOST_ASIO_DISABLE_MOVE definition macro or activated by the BOOST_ASIO_HAS_MOVE macro. Note these Macros also affect movable IO objects. #### []() Variable parameter template If the compiler supports it, Boost.Asio can use variable parameter templates to implement [basic_socket_streambuf::connect()](<> "basic_socket_streambuf::connect") and [basic_socket_iostream::connect()](<> "basic_socket_iostream::connect ")function. The variable parameter template supports the addition of `-std=c++0x` or `-std=gnu++0x` compilation option at compile time in g++4.3 and later versions, which will be automatically activated. It can be disabled using the BOOST_ASIO_DISABLE_VARIADIC_TEMPLATES macro, use The BOOST_ASIO_HAS_VARIADIC_TEMPLATES macro is activated. #### []()Array container Since the standard library provides std::array<>, Boost.Asio: * Provides an overload for the buffer() function. * Relative to [ip::address_v4::bytes_type](<> "ip::address_v4::bytes_type") and [ip::address_v6::bytes_type](<> "ip::address_v6::bytes_type") priority use boost::array<>. * For fixed-size arrays, boost::array<> is preferred. G++4.3 and later versions add `-std=c++0x` or `-std=gnu++0x` compilation option to automatically activate std::array<>, and VC++10 also supports it. Use BOOST_ASIO_DISABLE_STD_ARRAY macro to disable, or BOOST_ASIO_HAS_STD_ARRAY macro to activate. #### []() primitive The implementation of Boost.Asio uses std::atomic<> in preference to boost::detail::atomic_count. Add the `-std=c++0x` or `-std=gnu++0x` compilation option in g++4.5 and later versions to activate the standard primitive integer template. It can be disabled using the BOOST_ASIO_DISABLE_STD_ATOMIC macro, or the BOOST_ASIO_HAS_STD_ATOMIC macro Enable. #### []()Share pointer Boost.Asio preferentially uses std::shared_ptr<> and std::weak_ptr<>. ### In g++4.3 and later versions, adding compilation options during compilation will automatically activate smart pointers, and MC++10 is the same. You can define BOOST_ASIO_DISABLE_STD_SHARED_PTR macro to disable, and use BOOST_ASIO_HAS_STD_SHARED_PTR macro to activate. #### []()[Chrono](<> "Chrono") Boost.Asio provides basic timer functions based on the std::chrono mechanism through the [basic_waitable_timer](<> "basic_waitable_timer") class template. [system_timer](<> "system_timer"),[steady_timer](<> "steady_timer" ) And [high_resolution_timer](<> "high_resolution_timer") use system_clock, steady_clock and high_resolution_clock standard clocks respectively. After g++ 4.6, add `-std=c++0x` or `-std=gnu++0x` compilation option to automatically support std::chrono. (Note that monotonic_clock is used instead of steady_clock in g++.) Use The BOOST_ASIO_DISABLE_STD_CHRONO macro is disabled, and the BOOST_ASIO_HAS_STD_CHRONO macro is activated. If chrono is not available, you can use the Boost.Chrono library. [basic_waitable_timer](<> "basic_waitable_timer") class is still available. ## []()Use Boost.Asio ### []()Support platform Tested under the following platforms and compilers: * Win32 and Win64 using Visual C++ 7.1 and Visual C++ 8.0. * Win32 using MinGW. * Win32 using Cygwin. (\__USE_W32\_SOCKETS must be defined.) * Linux (2.4 or 2.6 kernels) using g++ 3.3 or later. * Solaris using g++ 3.3 or later. * Mac OS X 10.4 using g++ 3.3 or later. It can also be used on the following platforms: * AIX 5.3 using XL C/C++ v9. * HP-UX 11i v3 using patched aC++ A.06.14. * QNX Neutrino 6.3 using g++ 3.3 or later. * Solaris using Sun Studio 11 or later. * Tru64 v5.1 using Compaq C++ v7.1. * Win32 using Borland C++ 5.9.2 ### []()Dependency In order for the program to connect to Boost.Asio the following libraries must be available: * Provide boost::system::error_code and boost::system::system_error Boost.System library. * If you use the read_until() or async_read_until() function with boost::regex parameter overload, the Boost.Regex library is required. * If you use Boost.Asio's SSL support, the OpenSSL library is required. And some examples require Boost.Thread, Boost.Date_Time or Boost.Serialization library support. | | **Note Note** | | ------------------------------------------------- -------------------------------------------------- -------------------------------- | ---------- | | In MSVC or Borland C++, you can add -DBOOST_DATE_TIME_NO_LIB and -DBOOST_REGEX_NO_LIB to the project settings to prohibit the automatic connection to the libraries Boost.Date_Time and Boost.Regex respectively. Otherwise, these libraries need to be generated and connected. | | ### []()Generate Boost library You can generate Boost sub-libraries as needed. The following example runs the command line in the root directory of Boost: Copy code

bjam --with-system --with-thread --with-date_time --with-regex --with-serialization stage

It is assumed that bjam has already been generated. See the Boost.Build documentation for more information. ### []()Optional independent compilation By default, Boost.Asio is only a library with header files. However, some developers prefer to compile the source code of Boost.Asio separately. You only need to add #include``\<boost/asio/to the source file of the program. impl/src.hpp>, and then add the BOOST_ASIO_SEPARATE_COMPILATION compilation option in the project/compiler settings and compile it. Or use the BOOST_ASIO_DYN_LINK option to independently compile Boost.Asio into a static library. If you use Boost.Asio's SSL support, you need to add #include` `\<boost/asio/ssl/impl/src.hpp>. ### []() Macro The macros in the following table can be used to control the behavior of Boost.Asio. | **Macro** | **Description**| | ------------------------------------- |-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------------------------------------------------------------ -------------------------------------------------- -------------------------------------------------- ------------------- | | BOOST_ASIO_ENABLE_BUFFER_DEBUGGING | Activates Boost.Asio's buffer debugging support, which can help identify invalid buffers referenced in read and write (for example, write data to std::string, but it has been released before the operation is completed). In Microsoft Visual C++, if you activate the iterative debugging support of the compiler, this macro will be automatically defined, otherwise you need to define BOOST_ASIO_DISABLE_BUFFER_DEBUGGING. In G++, if you start standard library debugging (the/_GLIBCXX_DEBUG macro is defined), this macro will be automatically defined, otherwise you need to define BOOST_ASIO_DISABLE_BUFFER_DEBUGGING Macro.||| | BOOST_ASIO_DISABLE_BUFFER_DEBUGGING | Explicitly disable Boost.Asio buffer debugging support.| | BOOST_ASIO_DISABLE_DEV_POLL | Explicitly disable Solaris `/dev/poll` support, and force the use of select-based implementation.| | BOOST_ASIO_DISABLE_EPOLL | Explicitly turn off Linux epoll support and force the use of select-based implementation.| | BOOST_ASIO_DISABLE_EVENTFD | Explicitly close Linux's eventfd support and force the use of pipes to interrupt blocking epoll/select system calls.| | BOOST_ASIO_DISABLE_KQUEUE | Explicitly disables kqueue support on Mac OS X and BSD variants, forcing the use of a select-based implementation.| | BOOST_ASIO_DISABLE_IOCP | Explicitly disables I/O completion ports support on Windows, forcing the use of a select-based implementation.| | BOOST_ASIO_DISABLE_THREADS | Explicitly disables Boost.Asio's threading support, independent of whether or not Boost as a whole supports threads.| | BOOST_ASIO_NO_WIN32\_LEAN_AND_MEAN | By default, Boost.Asio will automatically define WIN32\_LEAN_AND_MEAN when compiling for Windows, to minimise the number of Windows SDK header files and features that are included. The presence of BOOST_ASIO_NO_WIN32\_LEAN_AND_MEAN prevents being WIN32\_LEAN defined .||| | BOOST_ASIO_NO_NOMINMAX | By default, Boost.Asio will automatically define NOMINMAX when compiling for Windows, to suppress the definition of the min() and max() macros. The presence of BOOST_ASIO_NO_NOMINMAX prevents NOMINMAX from being defined.||| | BOOST_ASIO_NO_DEFAULT_LINKED_LIBS | When compiling for Windows using Microsoft Visual C++ or Borland C++, Boost.Asio will automatically link in the necessary Windows SDK libraries for sockets support (ie`ws2_32.lib`and`mswsock.lib`, or`ws2.lib` when building for Windows CE). The BOOST_ASIO_NO_DEFAULT_LINKED_LIBS macro prevents these libraries from being linked.||| | BOOST_ASIO_SOCKET_STREAMBUF_MAX_ARITY | Determines the maximum number of arguments that may be passed to the basic_socket_streambuf class template's connect member function. Defaults to 5.| | BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY | Determines the maximum number of arguments that may be passed to the basic_socket_iostream class template's constructor and connect member function. Defaults to 5.| | BOOST_ASIO_ENABLE_CANCELIO | Enables use of the CancelIo function on older versions of Windows. If not enabled, calls to cancel() on a socket object will always fail with asio::error::operation_not_supported when run on Windows XP, Windows Server 2003, and earlier versions of Windows. When running on Windows Vista, Windows Server 2008, and later, the CancelIoEx function is always used. The CancelIo function has two issues that should be considered before enabling its use:\* It will only cancel asynchronous operations that were initiated in the current thread.\* It can appear to complete without error, but the request to cancel the unfinished operations may be silently ignored by the operating system. Whether it works or not seems to depend on the drivers that are installed.For portable cancellation,consider using one of the following alternatives:\* Disable asio's I/O completion port backend by defining BOOST_ASIO_DISABLE_IOCP.\* Use the socket object's close() function to simultaneously cancel the outstanding operations and close the socket. | | BOOST_ASIO_NO_TYPEID | Disables uses of the typeid operator in Boost.Asio. Defined automatically if BOOST_NO_TYPEID is defined.| | BOOST_ASIO_HASH_MAP_BUCKETS | Determines the number of buckets in Boost.Asio's internal hash_map objects. The value should be a comma separated list of prime numbers, in ascending order. The hash_map implementation will automatically increase the number of buckets as the number of elements in the map increases.Some examples:\* Defining BOOST_ASIO_HASH_MAP_BUCKETS to 1021 means that the hash_map objects will always contain 1021 buckets, irrespective of the number of elements in the map.\* Defining BOOST_ASIO_HASH_MAP_BUCKETS to 53,389,1543 means that the hash_map objects will initially contain 53 buckets . The number of buckets will be increased to 389 and then 1543 as elements are added to the map.| ### []()mailing list The mailing list of Boost.Asio can be found from [SourceForge.net](http://sourceforge.net/mail/?group_id=122478). For newsgroups, see [Gmane](http://dir.gmane.org/gmane. comp.lib.boost.asio.user). ### []()[Wiki]() Users usually benefit from sharing examples, tips and FAQs on the Boost.Asio WIKI. Please see <http://think-async.com/Asio/>. ## []()Getting Started Tutorial basic skills The first section of the introductory tutorial introduces the basic concepts of using the asio tool. Before developing a complex network program, the sample program explains the basic skills of using asynchronous timers. * [Timer.1-Using a timer synchronously](<> "Timer.1-Using a timer synchronously") Synchronous timing program * [Timer.2-Using a timer asynchronously](<> "Timer.2-Using a timer asynchronously") Asynchronous timing program * [Timer.3-Binding arguments to a handler](<> "Timer.3-Binding arguments to a handler") bind parameters to a handler * [Timer.4-Using a member function as a handler](<> "Timer.4-Using a member function as a handler") * [Timer.5-Synchronising handlers in multithreaded programs](<> "Timer.5-Synchronising handlers in multithreaded programs") Introduction to Sockets This tutorial shows how to use asio to develop a simple client and server program. The program uses TCP and UDP to implement the basic daytime protocol. The first three programs use TCP to implement the daytime protocol. * [Daytime.1-A synchronous TCP daytime client](<> "Daytime.1-A synchronous TCP daytime client") * [Daytime.2-A synchronous TCP daytime server](<> "Daytime.2-A synchronous TCP daytime server") * [Daytime.3-An asynchronous TCP daytime server](<> "Daytime.3-An asynchronous TCP daytime server") The following three programs use UDP to implement the daytime protocol. * [Daytime.4-A synchronous UDP daytime client](<> "Daytime.4-A synchronous UDP daytime client") * [Daytime.5-A synchronous UDP daytime server](<> "Daytime.5-A synchronous UDP daytime server") * [Daytime.6-An asynchronous UDP daytime server](<> "Daytime.6-An asynchronous UDP daytime server") The program at the end of this section shows how to use asio to combine TCP and UDP services in one program. * [Daytime.7-A combined TCP/UDP asynchronous server](<> "Daytime.7-A combined TCP/UDP asynchronous server") ### []()Timer 1-Use synchronous timer This tutorial demonstrates how to use asio's timer to perform blocking wait. **Necessary header files need to be included:** Simply include the "asio.hpp" header file to use all asio classes. Copy code

#include

Copy code

#include <boost/asio.hpp>

Since the timer is used in this example, the corresponding Boost.Date_Time header file needs to be included to facilitate the operation of the timer. Copy code

#include <boost/date_time/posix_time/posix_time.hpp>

All programs that use asio must create an io_service object. This class provides IO function support. The object of this class is first declared in the main function. Copy code

int main()

Copy code

{

Copy code

  boost::asio::io_service io;

Then declare an object of type boost::asio::deadline_timer. The first parameter of the core asio class (or timer function) constructor that provides IO functions is always an instance of the io_service class. The second parameter sets the expiration time For 5 seconds from now. Copy code

  boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));

This is a simple example of blocking waiting on a timer. Calling [deadline_timer::wait()](<> "basic_deadline_timer::wait") will return after the timer expires (5 seconds). Timers always have two states: "expired" or "unexpired". If the [deadline_timer::wait()](<> "basic_deadline_timer::wait") function is executed on an expired time, it will Return immediately. Copy code

  t.wait();

Finally, after the time expires, the famous "Hello, world!" message is output. Copy code

  std::cout << "Hello, world!\n";

Copy code

  return 0;

Copy code

}

### []()Timer 2--Use timer asynchronously This example modifies the time1 example and demonstrates how to use the asio asynchronous callback function by asynchronously waiting on the timer. Copy code

#include

Copy code

#include <boost/asio.hpp>

Copy code

#include <boost/date_time/posix_time/posix_time.hpp>

Using the asynchronous function of asio means that you need to define a callback function to be executed after the asynchronous operation is completed. This program defines a function called print, which is called after the asynchronous wait is completed. Copy code

void print(const boost::system::error_code&/e/)

Copy code

{

Copy code

  std::cout << "Hello, world!\n";

Copy code

}

Copy code

 

Copy code

int main()

Copy code

{

Copy code

  boost::asio::io_service io;

Copy code

 

Copy code

  boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));

Next, replace the blocking wait in Example 1. Call [deadline_timer::async_wait()](<> "basic_deadline_timer::async_wait") function to perform asynchronous wait. In this function, the print callback function defined above is passed. Copy code

  t.async_wait(&print);

Finally, the io_service::run() member function must be called on the io_service object. The Asio library guarantees that the callback function is executed on the thread that called io_service::run(). Therefore, only the io_service::run() function is called, the callback function that asynchronously waits for completion can be called. Io_service::run() will always run because it still has work to do. In this example, this work is asynchronously waiting for the timer, so it will not exit until the timer expires and the callback function is executed. It is important to assign a job to io_service::run() before calling it. For example, if you forget to call [deadline_timer::async_wait()](<> "basic_deadline_timer::async_wait") in the above example, io_service has nothing to do , The io_service::run() call will return immediately. Copy code

  io.run();

Copy code

  return 0;

Copy code

}

### []()Timer 3-Passing parameters to the processor This program is modified from the Timer2 program, and the timer is changed to trigger once per second. It is used to explain how to pass other parameters to the processing function. Copy code

#include

Copy code

#include <boost/asio.hpp>

Copy code

#include <boost/bind.hpp>

Copy code

#include <boost/date_time/posix_time/posix_time.hpp>

In order to make the timer cycle expire, you need to modify the timer's expiration time in the callback function, and then start a new asynchronous wait. Of course, the callback function must be able to access the timer object. To achieve this effect, you need to pass two parameters to the print function: * Pointer to the timer object. * Timer triggers the counter so that the program runs after 6 triggers. Copy code

void print(const boost::system::error_code&/e/,

Copy code

    boost::asio::deadline_timer* t, int* count)

Copy code

{

As mentioned above, the program uses a timer to stop running, and if the timer triggers the test more than 6 times, it exits. However, there is no explicit stop io_service. In the timer 2 example, we know that only when there is nothing to do io_service::run() will exit. When the counter is equal to 5, no new asynchronous wait is started, and the io_service has completed its work and stops running. Copy code

  if (*count <5)

Copy code

  {

Copy code

    std::cout << *count << "\n";

Copy code

    ++(*count);

In addition, the expiration time is delayed by one second from the previous expiration time. Defining a new expiration time on the original basis can ensure that the number of seconds marked by the timer will not be delayed due to the execution of the processing function. Copy code

    t->expires_at(t->expires_at() + boost::posix_time::seconds(1));

Then start a new asynchronous wait on the timer. The boost::bind() function is used to associate the callback function with the parameter. [deadline_timer::async_wait()](<> "basic_deadline_timer::async_wait") The desired callback of the function The function form is void(const` `boost::system::error_code&).The bind function converts the callback function print together with additional parameters into this correct function signature. For more information about Boost.Bind, see [Boost.Bind documentation](http://www.boost.org/libs/bind/bind.html). In this example, the boost::asio::placeholders::error parameter of boost::bind() is a placeholder for the name of the error object passed to the function. If you use boost::bind() to initialize asynchronous operations, you must specify The parameter consistent with the handle parameter list. In example 4, the callback function does not need this parameter and will be omitted. Copy code

    t->async_wait(boost::bind(print,

Copy code

          boost::asio::placeholders::error, t, count));

Copy code

  }

Copy code

}

Copy code

 

Copy code

int main()

Copy code

{

Copy code

  boost::asio::io_service io;

Add a new count variable to end the program after the timer is triggered 6 times. Copy code

  int count = 0;

Copy code

  boost::asio::deadline_timer t(io, boost::posix_time::seconds(1));

As in step 4, when [deadline_timer::async_wait()](<> "basic_deadline_timer::async_wait") is called in the main function, additional parameters are passed to the print function. Copy code

  t.async_wait(boost::bind(print,

Copy code

        boost::asio::placeholders::error, &t, &count));

Copy code

 

Copy code

  io.run();

Finally, verify the count variable in the print handle function and output its value. Copy code

  std::cout << "Final count is "<< count << "\n";

Copy code

 

Copy code

  return 0;

Copy code

}

### []()[Timer 4-Using a member function as a handler](<> "Timer.4-Using a member function as a handler") This example demonstrates how to use the member function of the class as a callback processing function. The program function is exactly the same as Timer3. Copy code

#include

Copy code

#include <boost/asio.hpp>

Copy code

#include <boost/bind.hpp>

Copy code

#include <boost/date_time/posix_time/posix_time.hpp>

In the previous example, the print function is used as the callback processing function. In this example, a printer class is first defined. Copy code

class printer

Copy code

{

Copy code

public:

There is a reference to io_service in the constructor of the class, which is used to initialize the timer\_ member. The timer that closes the program is also declared as a member of the class. Copy code

  printer(boost::asio::io_service& io)

Copy code

    : timer_(io, boost::posix_time::seconds(1)),

Copy code

      count_(0)

Copy code

  {

The Boost::bind() function can also be used to handle class member functions. Since all non-static class member functions have an implicit this parameter, we need to bind this to the function. Like the Timer3 example, use boost ::bind() converts the callback processing function and treats it as a signature in the form of void (const, boost::system::error_code&). Note here that boost::asio::placeholders::error placeholders are ignored, and the member function print does not receive error object parameters. Copy code

    timer_.async_wait(boost::bind(&printer::print, this));

Copy code

  }

The final counter value is output in the destructor of the class. Copy code

  ~printer()

Copy code

  {

Copy code

    std::cout << "Final count is "<< count_ << "\n";

Copy code

  }

The member function print is very similar to the print function in the previous example. Since the counter and timer are both members of the class, there is no need to pass parameters. Copy code

  void print()

Copy code

  {

Copy code

    if (count_ <5)

Copy code

    {

Copy code

      std::cout << count_ << "\n";

Copy code

      ++count_;

Copy code

 

Copy code

      timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));

Copy code

      timer_.async_wait(boost::bind(&printer::print, this));

Copy code

    }

Copy code

  }

Copy code

 

Copy code

private:

Copy code

  boost::asio::deadline_timer timer_;

Copy code

  int count_;

Copy code

};

The Main function is also very similar to the previous example, now declare a printer object and run io_service. Copy code

int main()

Copy code

{

Copy code

  boost::asio::io_service io;

Copy code

  printer p(io);

Copy code

  io.run();

Copy code

 

Copy code

  return 0;

Copy code

}

### []()Sync TCP daytime client This example shows how to use asio to implement a TCP client. **Need to include the following header files.** Copy code

#include

Copy code

#include <boost/array.hpp>

Copy code

#include <boost/asio.hpp>

The purpose of the program is to access the daytime server, so the user needs to specify a server. Copy code

using boost::asio::ip::tcp;

Copy code

 

Copy code

int main(int argc, char* argv[])

Copy code

{

Copy code

  try

Copy code

  {

Copy code

    if (argc != 2)

Copy code

    {

Copy code

      std::cerr << "Usage: client "<< std::endl;

Copy code

      return 1;

Copy code

    }

All programs that use asio need an [io_service](<> "io_service") object. Copy code

    boost::asio::io_service io_service;

We need to convert the server name specified in the program parameters to a TCP endpoint, so we need to define an [ip::tcp::resolver](<> "ip::tcp::resolver") object. Copy code

    tcp::resolver resolver(io_service);

The analyzer uses a query object and obtains a list of endpoints. The name of the server (parameter argv\[1]) and the name of the service (daytime in this case) are used as parameters to construct the query object. Copy code

    tcp::resolver::query query(argv[1], "daytime");

The returned endpoint list is an iterator of type [ip::tcp::resolver::iterator](<> "ip::basic_resolver::iterator"). Copy code

    tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);

Now create and connect the Socket. The above endpoint list may include IPv4 or IPv6 type endpoints, you need to try each possible endpoint. This way the client is independent of the IP version number. boost::asio::connect() automatically Complete these functions. Copy code

    tcp::socket socket(io_service);

Copy code

    boost::asio::connect(socket, endpoint_iterator);

The connection has been opened. Now you can read data from the server. Use boost::array to receive data. The boost::asio::buffer() function automatically manages the size of the array to prevent buffer overflow. In addition to boost::array, you can also use char\[] or std::vector. Copy code

    for (;;)

Copy code

    {

Copy code

      boost::array<char, 128> buf;

Copy code

      boost::system::error_code error;

Copy code

 

Copy code

      size_t len = socket.read_some(boost::asio::buffer(buf), error);

When the server closes the connection, the [ip::tcp::socket::read_some()](<> "basic_stream_socket::read_some") function receives the boost::asio::error::eof error message and exits the client cycle. Copy code

      if (error == boost::asio::error::eof)

Copy code

        break;//Connection closed cleanly by peer.

Copy code

      else if (error)

Copy code

        throw boost::system::system_error(error);//Some other error.

Copy code

 

Copy code

      std::cout.write(buf.data(), len);

Copy code

    }

Finally, handle the exceptions that may be thrown. Copy code

  }

Copy code

  catch (std::exception& e)

Copy code

  {

Copy code

    std::cerr << e.what() << std::endl;

Copy code

  }

### []()TCP daytime synchronization server This example illustrates how to use asio to implement a TCP server application. Copy code

#include

Copy code

#include

Copy code

#include

Copy code

#include <boost/asio.hpp>

Copy code

 

Copy code

using boost::asio::ip::tcp;

Define a make_daytime_string() function to generate the string sent to the client. This function is reused in all daytime service applications. Copy code

std::string make_daytime_string()

Copy code

{

Copy code

  using namespace std;//For time_t, time and ctime;

Copy code

  time_t now = time(0);

Copy code

  return ctime(&now);

Copy code

}

Copy code

 

Copy code

int main()

Copy code

{

Copy code

  try

Copy code

  {

Copy code

    boost::asio::io_service io_service;

[ip::tcp::acceptor](<> "ip::tcp::acceptor") The object is used to listen for new connections. It is initialized here to use the IPv4 protocol to listen on port 13. Copy code

    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 13));

This is an iterable server, that is, it can only handle one connection at a time. Create a Socket for each client connection, and then wait for new connections. Copy code

    for (;;)

Copy code

    {

Copy code

      tcp::socket socket(io_service);

Copy code

      acceptor.accept(socket);

The client visits our server. The current time will be passed to the client. Copy code

      std::string message = make_daytime_string();

Copy code

 

Copy code

      boost::system::error_code ignored_error;

Copy code

      boost::asio::write(socket, boost::asio::buffer(message), ignored_error);

Copy code

    }

Copy code

  }

Finally handle the exception. Copy code

  catch (std::exception& e)

Copy code

  {

Copy code

    std::cerr << e.what() << std::endl;

Copy code

  }

Copy code

 

Copy code

  return 0;

Copy code

}

### []()Asynchronous TCP daytime server **main function** Copy code

int main()

Copy code

{

Copy code

  try

Copy code

  {

First create a service object to receive the client connection. [io_service](<> "io_service") object provides IO service, such as socket uses this IO service object. Copy code

    boost::asio::io_service io_service;

Copy code

    tcp_server server(io_service);

Run the [io_service](<> "io_service") object to perform asynchronous operations. Copy code

    io_service.run();

Copy code

  }

Copy code

  catch (std::exception& e)

Copy code

  {

Copy code

    std::cerr << e.what() << std::endl;

Copy code

  }

Copy code

 

Copy code

  return 0;

Copy code

}

**tcp_server class** Copy code

class tcp_server

Copy code

{

Copy code

public:

The constructor initializes the receiver to listen on port 13 of TCP. Copy code

  tcp_server(boost::asio::io_service& io_service)

Copy code

    : acceptor_(io_service, tcp::endpoint(tcp::v4(), 13))

Copy code

  {

Copy code

    start_accept();

Copy code

  }

Copy code

 

Copy code

private:

The function start_accept() creates a Socket and initializes it as an asynchronous receiving operation, waiting for a new connection. Copy code

  void start_accept()

Copy code

  {

Copy code

    tcp_connection::pointer new_connection =

Copy code

      tcp_connection::create(acceptor_.get_io_service());

Copy code

 

Copy code

    acceptor_.async_accept(new_connection->socket(),

Copy code

        boost::bind(&tcp_server::handle_accept, this, new_connection,

Copy code

          boost::asio::placeholders::error));

Copy code

  }

After the asynchronous receiving operation initiated by the start_accept() function is completed, the handle_accept() function is called. It responds to the client's request and calls the start_accept() function again to initiate the next receiving operation. Copy code

  void handle_accept(tcp_connection::pointer new_connection,

Copy code

      const boost::system::error_code& error)

Copy code

  {

Copy code

    if (!error)

Copy code

    {

Copy code

      new_connection->start();

Copy code

    }

Copy code

 

Copy code

    start_accept();

Copy code

  }

**Tcp connection class** Use shared_ptr and enable_shared_from_this to ensure that tcp_connetion remains active during the corresponding operation. Copy code

class tcp_connection

Copy code

  : public boost::enable_shared_from_this<tcp_connection>

Copy code

{

Copy code

public:

Copy code

  typedef boost::shared_ptr<tcp_connection> pointer;

Copy code

 

Copy code

  static pointer create(boost::asio::io_service& io_service)

Copy code

  {

Copy code

    return pointer(new tcp_connection(io_service));

Copy code

  }

Copy code

 

Copy code

  tcp::socket& socket()

Copy code

  {

Copy code

    return socket_;

Copy code

  }

In the function start(), call boost::asio::async_write() to write data to the client. Note that boost::asio::async_write() is used instead of [ip::tcp::socket::async_write_some() ](<> "basic_stream_socket::async_write_some"), this will ensure that all data is sent. Copy code

  void start()

Copy code

  {

The sent data is stored in the class member message\_, and the validity of the data must be guaranteed before the asynchronous operation is completed. Copy code

    message_ = make_daytime_string();

After initializing the asynchronous operation, the parameters passed using boost::bind() must match the event handler parameter list. In this example, boost::asio::placeholders::error and boost::asio::placeholders::bytes_transferred The parameter placeholders have been removed because they are not used in handle_write(). Copy code

    boost::asio::async_write(socket_, boost::asio::buffer(message_),

Copy code

        boost::bind(&tcp_connection::handle_write, shared_from_this(),

Copy code

          boost::asio::placeholders::error,

Copy code

          boost::asio::placeholders::bytes_transferred));

Handling the client connection request again needs to be handled by handle_write(). Copy code

  }

Copy code

 

Copy code

private:

Copy code

  tcp_connection(boost::asio::io_service& io_service)

Copy code

    : socket_(io_service)

Copy code

  {

Copy code

  }

Copy code

 

Copy code

  void handle_write(const boost::system::error_code&/error/,

Copy code

      size_t/bytes_transferred/)

Copy code

  {

Copy code

  }

Copy code

 

Copy code

  tcp::socket socket_;

Copy code

  std::string message_;

Copy code

};

**Remove useless event handler parameters** You may find that the error and bytes_transferred parameters are useless in the function handle_write(). If the parameters are not needed, they can be removed: Copy code

  void handle_write()

Copy code

  {

Copy code

  }

The call of boost::asio::async_write() is adjusted to the following form: Copy code

  boost::asio::async_write(socket_, boost::asio::buffer(message_),

Copy code

      boost::bind(&tcp_connection::handle_write, shared_from_this()));

### []()DDaytime4-Synchronous UDP daytime client This sample program shows how to use asio to implement a UPD client program. \#include/span>/<iostream> \#include/<boost/array.hpp> \#include/<boost/asio.hpp>   using boost::asio::ip::udp;; The way to start the program is the same as the TCP daytime client. int/span> main(int argc, char\* argv\[]) {<!-- -->   try   {<!-- -->     if (argc != 2)     {<!-- -->       std::cerr << "Usage: client/<host>" << std::endl;       return 1;     }       boost::asio::io_service io_service;; Pass the host and service name to [ip::udp::resolver](<> "ip::udp::resolver") to obtain the correct remote endpoint. The query passes [ip::udp::v4()](<> "ip::udp::v4") parameter restriction makes it return an IPv4 protocol endpoint.     udp::resolver resolver(io_service);     udp::resolver::query query(udp::v4(), argv\[1], "daytime")); The [ip::udp::resolver::resolve()](<> "ip::basic_resolver::resolve") function guarantees that if the query is successful, it will return a list of at least one endpoint. Therefore, it is safe to directly respond to the return value Dereference. [udp::endpoint receiver_endpoint =/*resolver.resolve(query));](<> "ip::basic_resolver::resolve") [Since UDP is based on datagrams, no stream-based Socket is used. Create one](<> "ip::basic_resolver::resolve")[ip::udp::socket](<> "ip::udp: :socket") and use the remote endpoint for the initial connection. [udp::socket socket(io_service);](<> "ip::udp::socket") [socket.open(udp::v4());](<> "ip::udp::socket") [boost::array\<char, 1> send_buf = {<!-- -->{ 0 }};](<> "ip::udp::socket") [socket.send_to(boost::asio::buffer(send_buf), receiver_endpoint));](<> "ip::udp::socket") [Now you need to be ready to receive the data sent by the server. The endpoint of the client to receive the server response must pass](<> "ip::udp::socket")[ip::udp::socket::receive_from() ](<> "basic_datagram_socket::receive_from") specified. [boost::array\<char, 128> recv_buf;](<> "basic_datagram_socket::receive_from") [udp::endpoint sender_endpoint;](<> "basic_datagram_socket::receive_from") [size_t len = socket.receive_from(](<> "basic_datagram_socket::receive_from") [boost::asio::buffer(recv_buf), sender_endpoint);](<> "basic_datagram_socket::receive_from") [std::cout.write(recv_buf.data(), len);](<> "basic_datagram_socket::receive_from") [}}](<> "basic_datagram_socket::receive_from")   [catch (std/span>::exception& e)](<> "basic_datagram_socket::receive_from") [{<!-- -->](<> "basic_datagram_socket::receive_from") [std::cerr << e.what() << std::endl;](<> "basic_datagram_socket::receive_from") [}](<> "basic_datagram_socket::receive_from") [return 0;](<> "basic_datagram_socket::receive_from") [}](<> "basic_datagram_socket::receive_from") ### []()Daytime5- daytime synchronization UDP server This sample program shows how to use asio to implement a synchronous UDP service program. Copy code

int main()

Copy code

{

Copy code

  try

Copy code

  {

Copy code

    boost::asio::io_service io_service;

Create an ip::udp::socket object to receive requests on UDP port 13. Copy code

    udp::socket socket(io_service, udp::endpoint(udp::v4(), 13));

Waiting for the client to request a connection. The remote_endpoint object will be passed into the [ip::udp::socket::receive_from()](<> "basic_datagram_socket::receive_from") function. Copy code

    for (;;)

Copy code

    {

Copy code

      boost::array<char, 1> recv_buf;

Copy code

      udp::endpoint remote_endpoint;

Copy code

      boost::system::error_code error;

Copy code

      socket.receive_from(boost::asio::buffer(recv_buf),

Copy code

          remote_endpoint, 0, error);

Copy code

 

Copy code

      if (error && error != boost::asio::error::message_size)

Copy code

        throw boost::system::system_error(error);

Then implement sending data to the client. Copy code

      std::string message = make_daytime_string();

Send a response to remote_endpoint. Copy code

      boost::system::error_code ignored_error;

Copy code

      socket.send_to(boost::asio::buffer(message),

Copy code

          remote_endpoint, 0, ignored_error);

Copy code

    }

Copy code

  }

Finally handle the exception. Copy code

  catch (std::exception& e)

Copy code

  {

Copy code

    std::cerr << e.what() << std::endl;

Copy code

  }

Copy code

 

Copy code

  return 0;

Copy code

}

### []()Daytime6- daytime asynchronous UDP server **main() function** Copy code

int main()

Copy code

{

Copy code

  try

Copy code

  {

Create a service object to receive client requests and run the io_service object. Copy code

    boost::asio::io_service io_service;

Copy code

    udp_server server(io_service);

Copy code

    io_service.run();

Copy code

  }

Copy code

  catch (std::exception& e)

Copy code

  {

Copy code

    std::cerr << e.what() << std::endl;

Copy code

  }

Copy code

 

Copy code

  return 0;

Copy code

}

**udp_server class** Copy code

class udp_server

Copy code

{

Copy code

public:

The constructor initializes the socket and listens on port 13 of UDP. Copy code

  udp_server(boost::asio::io_service& io_service)

Copy code

    : socket_(io_service, udp::endpoint(udp::v4(), 13))

Copy code

  {

Copy code

    start_receive();

Copy code

  }

Copy code

 

Copy code

private:

Copy code

  void start_receive()

Copy code

  {

The [ip::udp::socket::async_receive_from()](<> "basic_datagram_socket::async_receive_from") function makes the application listen for new requests in the background. When the request is received, the io_service object uses two parameters to call handle_receive Function: A boost::system::error_code type parameter describing the success or failure of the operation, and a size_t type bytes_transferred to specify the number of bytes received. Copy code

    socket_.async_receive_from(

Copy code

        boost::asio::buffer(recv_buffer_), remote_endpoint_,

Copy code

        boost::bind(&udp_server::handle_receive, this,

Copy code

          boost::asio::placeholders::error,

Copy code

          boost::asio::placeholders::bytes_transferred));

Copy code

  }

The handle_receive() function handles client requests. Copy code

  void handle_receive(const boost::system::error_code& error,

Copy code

      std::size_t/bytes_transferred/)

Copy code

  {

The error parameter contains the result of the asynchronous operation. Since only one byte of recv_buffer\_ is provided to store the client request, if the data sent by the client is too long, the io_service will return an error message. If an error occurs, it will be ignored. Copy code

    if (!error || error == boost::asio::error::message_size)

Copy code

    {

Generate the data sent to the client. Copy code

      boost::shared_ptr std::string message(

Copy code

          new std::string(make_daytime_string()));

Call [ip::udp::socket::async_send_to()](<> "basic_datagram_socket::async_send_to") function to send data to the client. Copy code

      socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint_,

Copy code

          boost::bind(&udp_server::handle_send, this, message,

Copy code

            boost::asio::placeholders::error,

Copy code

            boost::asio::placeholders::bytes_transferred));

When initializing an asynchronous operation, if you use boost::bind(), you must specify a parameter list that matches the callback function. In this program, two parameter placeholders (boost::asio::placeholders::error and boost: :asio::placeholders::bytes_transferred) should be removed. Start listening for the next client request. Copy code

      start_receive();

More processing of customer requests is handled by handle_send(). Copy code

    }

Copy code

  }

The handle_send() function is called after the service request ends. Copy code

  void handle_send(boost::shared_ptr std::string/message/,

Copy code

      const boost::system::error_code&/error/,

Copy code

      std::size_t/bytes_transferred/)

Copy code

  {

Copy code

  }

Copy code

 

Copy code

  udp::socket socket_;

Copy code

  udp::endpoint remote_endpoint_;

Copy code

  boost::array<char, 1> recv_buffer_;

Copy code

};

### []()Daytime7-TCP/UDP asynchronous service This sample program shows how to integrate the two asynchronous services that have been written into one service program. **main() function** Copy code

int main()

Copy code

{

Copy code

  try

Copy code

  {

Copy code

    boost::asio::io_service io_service;

Create a service object that receives TCP client connections. Copy code

    tcp_server server1(io_service);

Create a service object that receives requests from UDP clients. Copy code

    udp_server server2(io_service);

Two work objects based on the io_service object have been created. Copy code

    io_service.run();

Copy code

  }

Copy code

  catch (std::exception& e)

Copy code

  {

Copy code

    std::cerr << e.what() << std::endl;

Copy code

  }

Copy code

 

Copy code

  return 0;

Copy code

}

**tcp_connection and tcp_server classes** The following two classes are taken from the Daytime3 example. Copy code

class tcp_connection

Copy code

  : public boost::enable_shared_from_this<tcp_connection>

Copy code

{

Copy code

public:

Copy code

  typedef boost::shared_ptr<tcp_connection> pointer;

Copy code

 

Copy code

  static pointer create(boost::asio::io_service& io_service)

Copy code

  {

Copy code

    return pointer(new tcp_connection(io_service));

Copy code

  }

Copy code

 

Copy code

  tcp::socket& socket()

Copy code

  {

Copy code

    return socket_;

Copy code

  }

Copy code

 

Copy code

  void start()

Copy code

  {

Copy code

    message_ = make_daytime_string();

Copy code

 

Copy code

    boost::asio::async_write(socket_, boost::asio::buffer(message_),

Copy code

        boost::bind(&tcp_connection::handle_write, shared_from_this()));

Copy code

  }

Copy code

 

Copy code

private:

Copy code

  tcp_connection(boost::asio::io_service& io_service)

Copy code

    : socket_(io_service)

Copy code

  {

Copy code

  }

Copy code

 

Copy code

  void handle_write()

Copy code

  {

Copy code

  }

Copy code

 

Copy code

  tcp::socket socket_;

Copy code

  std::string message_;

Copy code

};

Copy code

 

Copy code

class tcp_server

Copy code

{

Copy code

public:

Copy code

  tcp_server(boost::asio::io_service& io_service)

Copy code

    : acceptor_(io_service, tcp::endpoint(tcp::v4(), 13))

Copy code

  {

Copy code

    start_accept();

Copy code

  }

Copy code

 

Copy code

private:

Copy code

  void start_accept()

Copy code

  {

Copy code

    tcp_connection::pointer new_connection =

Copy code

      tcp_connection::create(acceptor_.get_io_service());

Copy code

 

Copy code

    acceptor_.async_accept(new_connection->socket(),

Copy code

        boost::bind(&tcp_server::handle_accept, this, new_connection,

Copy code

          boost::asio::placeholders::error));

Copy code

  }

Copy code

 

Copy code

  void handle_accept(tcp_connection::pointer new_connection,

Copy code

      const boost::system::error_code& error)

Copy code

  {

Copy code

    if (!error)

Copy code

    {

Copy code

      new_connection->start();

Copy code

    }

Copy code

 

Copy code

    start_accept();

Copy code

  }

Copy code

 

Copy code

  tcp::acceptor acceptor_;

Copy code

};

**udp_server class** Similarly, the following class is taken from the previous example. Copy code

class udp_server

Copy code

{

Copy code

public:

Copy code

  udp_server(boost::asio::io_service& io_service)

Copy code

    : socket_(io_service, udp::endpoint(udp::v4(), 13))

Copy code

  {

Copy code

    start_receive();

Copy code

  }

Copy code

 

Copy code

private:

Copy code

  void start_receive()

Copy code

  {

Copy code

    socket_.async_receive_from(

Copy code

        boost::asio::buffer(recv_buffer_), remote_endpoint_,

Copy code

        boost::bind(&udp_server::handle_receive, this,

Copy code

          boost::asio::placeholders::error));

Copy code

  }

Copy code

 

Copy code

  void handle_receive(const boost::system::error_code& error)

Copy code

  {

Copy code

    if (!error || error == boost::asio::error::message_size)

Copy code

    {

Copy code

      boost::shared_ptr std::string message(

Copy code

          new std::string(make_daytime_string()));

Copy code

 

Copy code

      socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint_,

Copy code

          boost::bind(&udp_server::handle_send, this, message));

Copy code

 

Copy code

      start_receive();

Copy code

    }

Copy code

  }

Copy code

 

Copy code

  void handle_send(boost::shared_ptr std::string/message/)

Copy code

  {

Copy code

  }

Copy code

 

Copy code

  udp::socket socket_;

Copy code

  udp::endpoint remote_endpoint_;

Copy code

  boost::array<char, 1> recv_buffer_;

Copy code

};

## []()Example ### []()Allocate memory This example shows how to allocate the necessary memory for asynchronous operations. * [boost_asio/example/allocation/server.cpp]() ### []()Buffer This example shows how to create a reference-counted buffer for Socket read and write operations. * [boost_asio/example/buffers/reference_counted.cpp]() ### []()Chat program This example implements the server and client of the chat program. This program uses a custom protocol with a 6-byte message header and a variable-length message body. * [boost_asio/example/chat/chat_message.hpp]() * [boost_asio/example/chat/chat_client.cpp]() * [boost_asio/example/chat/chat_server.cpp]() The following chat client for POSIX demonstrates how to use the [posix::stream_descriptor](<> "posix::stream_descriptor") class to perform console input and output. * [boost_asio/example/chat/posix_chat_client.cpp]() ### []()Echo Show how to implement a series of simple clients and servers using synchronous and asynchronous operations. * [boost_asio/example/echo/async_tcp_echo_server.cpp]() * [boost_asio/example/echo/async_udp_echo_server.cpp]() * [boost_asio/example/echo/blocking_tcp_echo_client.cpp]() * [boost_asio/example/echo/blocking_tcp_echo_server.cpp]() * [boost_asio/example/echo/blocking_udp_echo_client.cpp]() * [boost_asio/example/echo/blocking_udp_echo_server.cpp]() ### []()fock The sample program for POSIX demonstrates how to use Boost.Asio combined with the fork() system call. The first example illustrates how to start the daemon: * [boost_asio/example/fork/daemon.cpp]() The second example illustrates how to start the process in the completion handle. * [boost_asio/example/fork/process_per_connection.cpp]() ### []()HTTP client The sample program simply implements the HTTP1.0 client. The program demonstrates how to use the read_until and async_read_until functions. * [boost_asio/example/http/client/sync_client.cpp]() * [boost_asio/example/http/client/async_client.cpp]() ### []()HTTP service The example illustrates the use of asio to implement HTTP1.0 services in a single thread. It demonstrates how to execute a clear command to end unfinished asynchronous operations. * [boost_asio/example/http/server/connection.cpp]() * [boost_asio/example/http/server/connection.hpp]() * [boost_asio/example/http/server/connection_manager.cpp]() * [boost_asio/example/http/server/connection_manager.hpp]() * [boost_asio/example/http/server/header.hpp]() * [boost_asio/example/http/server/main.cpp]() * [boost_asio/example/http/server/mime_types.cpp]() * [boost_asio/example/http/server/mime_types.hpp]() * [boost_asio/example/http/server/reply.cpp]() * [boost_asio/example/http/server/reply.hpp]() * [boost_asio/example/http/server/request.hpp]() * [boost_asio/example/http/server/request_handler.cpp]() * [boost_asio/example/http/server/request_handler.hpp]() * [boost_asio/example/http/server/request_parser.cpp]() * [boost_asio/example/http/server/request_parser.hpp]() * [boost_asio/example/http/server/server.cpp]() * [boost_asio/example/http/server/server.hpp]() ### []()HTTP Service 2 HTTP service designed using io_service-per-CPU. * [boost_asio/example/http/server2/connection.cpp]() * [boost_asio/example/http/server2/connection.hpp]() * [boost_asio/example/http/server2/header.hpp]() * [boost_asio/example/http/server2/io_service_pool.cpp]() * [boost_asio/example/http/server2/io_service_pool.hpp]() * [boost_asio/example/http/server2/main.cpp]() * [boost_asio/example/http/server2/mime_types.cpp]() * [boost_asio/example/http/server2/mime_types.hpp]() * [boost_asio/example/http/server2/reply.cpp]() * [boost_asio/example/http/server2/reply.hpp]() * [boost_asio/example/http/server2/request.hpp]() * [boost_asio/example/http/server2/request_handler.cpp]() * [boost_asio/example/http/server2/request_handler.hpp]() * [boost_asio/example/http/server2/request_parser.cpp]() * [boost_asio/example/http/server2/request_parser.hpp]() * [boost_asio/example/http/server2/server.cpp]() * [boost_asio/example/http/server2/server.hpp]() ### []()HTTP service 3 Use a single io_service and call the HTTP service of io_service::run() on the thread pool. * [boost_asio/example/http/server3/connection.cpp]() * [boost_asio/example/http/server3/connection.hpp]() * [boost_asio/example/http/server3/header.hpp]() * [boost_asio/example/http/server3/main.cpp]() * [boost_asio/example/http/server3/mime_types.cpp]() * [boost_asio/example/http/server3/mime_types.hpp]() * [boost_asio/example/http/server3/reply.cpp]() * [boost_asio/example/http/server3/reply.hpp]() * [boost_asio/example/http/server3/request.hpp]() * [boost_asio/example/http/server3/request_handler.cpp]() * [boost_asio/example/http/server3/request_handler.hpp]() * [boost_asio/example/http/server3/request_parser.cpp]() * [boost_asio/example/http/server3/request_parser.hpp]() * [boost_asio/example/http/server3/server.cpp]() * [boost_asio/example/http/server3/server.hpp]() ### []()HTTP Service 4 Use stackless collaboration technology to implement single-threaded HTTP service. * [boost_asio/example/http/server4/coroutine.hpp]() * [boost_asio/example/http/server4/file_handler.cpp]() * [boost_asio/example/http/server4/file_handler.hpp]() * [boost_asio/example/http/server4/header.hpp]() * [boost_asio/example/http/server4/main.cpp]() * [boost_asio/example/http/server4/mime_types.cpp]() * [boost_asio/example/http/server4/mime_types.hpp]() * [boost_asio/example/http/server4/reply.cpp]() * [boost_asio/example/http/server4/reply.hpp]() * [boost_asio/example/http/server4/request.hpp]() * [boost_asio/example/http/server4/request_parser.cpp]() * [boost_asio/example/http/server4/request_parser.hpp]() * [boost_asio/example/http/server4/server.cpp]() * [boost_asio/example/http/server4/server.hpp]() * [boost_asio/example/http/server4/unyield.hpp]() * [boost_asio/example/http/server4/yield.hpp]() ### []()ICMP Show how to use native socket to ping remote host on ICMP. * [boost_asio/example/icmp/ping.cpp]() * [boost_asio/example/icmp/ipv4\_header.hpp]() * [boost_asio/example/icmp/icmp_header.hpp]() ### []()transfer Show how to customize function calls. Add completion handles to a priority queue instead of calling them directly. * [boost_asio/example/invocation/prioritised_handlers.cpp]() ### []()iostream Show how to use [ip::tcp::iostream](<> "ip::tcp::iostream"). * [boost_asio/example/iostreams/daytime_client.cpp]() * [boost_asio/example/iostreams/daytime_server.cpp]() * [boost_asio/example/iostreams/http_client.cpp]() ### []()Broadcast Demonstrate the use of broadcasting to transmit packages to the subscription group * [boost_asio/example/multicast/receiver.cpp]() * [boost_asio/example/multicast/sender.cpp]() ### []()Serialization Show how to use Boost.Serialization serial number and deserialization structure in asio, so as to realize the transmission of data objects on Socket. * [boost_asio/example/serialization/client.cpp]() * [boost_asio/example/serialization/connection.hpp]() * [boost_asio/example/serialization/server.cpp]() * [boost_asio/example/serialization/stock.hpp]() ### []()Service Show how to integrate custom functions into asio's io_service (in this case, the log function is added), and use custom services on [basic_stream_socket<>](<> "basic_stream_socket"). * [boost_asio/example/services/basic_logger.hpp]() * [boost_asio/example/services/daytime_client.cpp]() * [boost_asio/example/services/logger.hpp]() * [boost_asio/example/services/logger_service.cpp]() * [boost_asio/example/services/logger_service.hpp]() * [boost_asio/example/services/stream_socket_service.hpp]() ### []()SOCKS4 protocol The sample client program implements the SOCKS4 protocol for communicating through a proxy. * [boost_asio/example/socks4/sync_client.cpp]() * [boost_asio/example/socks4/socks4.hpp]() ### []()SSL The client and server sample programs demonstrate the use of the [ssl::stream<>](<> "ssl::stream") template in asynchronous operations. * [boost_asio/example/ssl/client.cpp]() * [boost_asio/example/ssl/server.cpp]() ### []()Timeout setting The following series of examples show how to cancel a long-running asynchronous operation after a specified time. * [boost_asio/example/timeouts/async_tcp_client.cpp]() * [boost_asio/example/timeouts/blocking_tcp_client.cpp]() * [boost_asio/example/timeouts/blocking_udp_client.cpp]() * [boost_asio/example/timeouts/server.cpp]() ### []()Timer The example demonstrates how to customize deadline_time to implement different types of timers. * [boost_asio/example/timers/tick_count_timer.cpp]() * [boost_asio/example/timers/time_t_timer.cpp]() ### []()[Porthopper]() This example demonstrates mixing synchronous and asynchronous operations and how to use Boost.Lambda in Boost.Asio. * [boost_asio/example/porthopper/protocol.hpp]() * [boost_asio/example/porthopper/client.cpp]() * [boost_asio/example/porthopper/server.cpp]() ### []() No blocking Show how to integrate third-party libraries that implement IO operations to achieve Reactor-style operations. * [boost_asio/example/nonblocking/third_party_lib.cpp]() ### []()Socket in UNIX Show how to use Socket in the UNIX field. * [boost_asio/example/local/connect_pair.cpp]() * [boost_asio/example/local/stream_server.cpp]() * [boost_asio/example/local/stream_client.cpp]() ### []()Windows Show how to use Windows-specific TransmitFile function in Boost.Asio. * [boost_asio/example/windows/transmit_file.cpp]() \ Copy code