Boost.asio C + + Network programming translator (6)

Source: Internet
Author: User
Tags epoll

Io_service class you should have found that most of the code written with Boost.asio uses several Ios_service instances. Ios_service is the most important class in this library, it is responsible for dealing with the operating system, waiting for the end of all asynchronous operations, and then invoking the completion handler for each asynchronous operation. If you choose to create your app in a synchronized way, you don't have to think about what I'm going to show you in this section. You can use Io_service in several different ways. In the following example, we have 3 asynchronous operations, 2 socket connections, and one timer waiting: one io_service and one single thread example: Io_service service_;
All the socket operations is handled by Service_
Ip::tcp::socket Sock1 (Service_);
All the socket operations is handled by Service_
Ip::tcp::socket Sock2 (Service_);
Sock1.async_connect (EP, Connect_handler);
Sock2.async_connect (EP, Connect_handler);
Deadline_timer T (service_, Boost::p osix_time::seconds (5));
T.async_wait (Timeout_handler);
Service_.run ();
Multithreaded example with a single io_service instance and multiple processing threads: Io_service service_;
Ip::tcp::socket Sock1 (Service_);
Ip::tcp::socket Sock2 (Service_);
Sock1.async_connect (EP, Connect_handler);
Sock2.async_connect (EP, Connect_handler);
Deadline_timer T (service_, Boost::p osix_time::seconds (5));
T.async_wait (Timeout_handler);
for (int i = 0; i < 5; ++i)
Boost::thread (Run_service);
void Run_service () {
Service_.run ();
}
Multi-threaded example with multiple Io_service instances and multiple processing threads: Io_service service_[2];
Ip::tcp::socket Sock1 (service_[0]);
Ip::tcp::socket Sock2 (service_[1]);
Sock1.async_connect (EP, Connect_handler);
Sock2.async_connect (EP, Connect_handler);
Deadline_timer T (Service_[0], boost::p osix_time::seconds (5));
T.async_wait (Timeout_handler);
for (int i = 0; i < 2; ++i)
Boost::thread (Boost::bind (Run_service, i));
void Run_service (int idx) {
Service_[idx].run ();
}
First, be aware that you cannot have multiple io_service but only one thread. The following code fragment has no meaning: for (int i = 0; i < 2; ++i)
Service_[i].run ();
The code snippet above is meaningless because service_[1].run () needs service_[0].run () to end first. Therefore, all asynchronous operations handled by service_[1] need to wait, which is obviously not a good idea. In the previous 3 scenarios, we were waiting for 3 asynchronous operations to end. To explain the differences between the points, we assume that the operation is completed in 1, then the Operation 2 is completed. We also assume that each completion handler takes 1 seconds to complete execution. In the first example, we wait for three operations to complete in one thread, and as soon as the 1th operation is complete, we call its completion handler. Although Operation 2 is completed shortly thereafter, the completion handler for Operation 2 needs to be called after the completion handler for Operation 1 is completed in 1 seconds. In the second example, we wait for 3 asynchronous operations to end in two threads. When Operation 1 is complete, we call its completion handler in the first thread. When Operation 2 is complete, then we call its completion handler in the second thread (when thread 1 is busy responding to the handler for Operation 1, thread 2 is idle and can respond to any new incoming operations). In the third example, because Operation 1 is sock1 Connect, Operation 2 is Sock2 's connect, so the application behaves as if it were a second example. Thread 1 handles the completion handler for the sock1 connect operation, and thread 2 processes the completion handler for the connect operation of Sock2. However, if the Sock1 connect operation is operation 1,deadline_timer t the timeout operation is action 2, thread 1 ends the completion handler for the Sock1 connect operation that is being processed. Thus, the timeout operation for Deadline_timer T must wait for the completion handler of the Sock1 connect operation to end (wait 1 seconds), because thread 1 handles the SOCK1 connection handler and T's timeout handler. Here's what you need to learn from the previous example: the first case is a very basic application. Because it is a serial way, you often encounter bottlenecks when several handlers are called at the same time. If a handler takes a long time to execute, all subsequent handlers have to wait. The second scenario is to compare the applicable applications. He is very strong--if several handlers are called at the same time (which is possible), they are called in the respective thread. The only bottleneck is that all the processing threads are busy while new handlers are called. However, there is a quick way to solve this problem by increasing the number of processing threads. The third situation is the most complex and most difficult to understand. You only use it if the second situation does not meet your needs. This is usually when you have thousands of real-time (socket) connections. You can thinkEach processing thread (the thread that runs Io_service::run () has its own select/epoll loop; it waits for any socket and then monitors a read-write operation that executes when it discovers such an operation. Most of the time, you don't have to worry about anything, the only thing you need to worry about is when the number of sockets you monitor grows exponentially (more than 1000 sockets). In that case, there are several select/epoll loops that increase the response time.
If you think you're an application that might need to be converted to a third mode, make sure that the code for the listen operation (the code that calls Io_service::run ()) and the rest of the application is isolated so that you can easily change it. Finally, keep in mind that if there are no other actions to monitor,. Run () will end, just like the code snippet given below: Io_service Service_;
Tcp::socket sock (Service_);
Sock.async_connect (EP, Connect_handler);
Service_.run ();
In the example above, as long as sock establishes a connection, Connect_handler will be called and then Service_.run () will complete execution. If you want to Service_.run () then execute, you need to assign more work to it. Here are two ways to accomplish this goal. One way is to start another asynchronous operation in Connect_handler to allocate more work. Another way to simulate some work to it, with the following code snippet:typedef boost::shared_ptr<io_service::work> WORK_PTR;
Work_ptr dummy_work (New Io_service::work (Service_));
The above code ensures that Service_.run () runs until you call Useservice_.stop () ordummy_work.reset (0);//Destroy Dummy_work.
Summary Boost.asio is a complex library, but it makes network programming incredibly simple. Compiling it is simple. It avoids the use of macros, which is good; although he defines a small number of macros to do the option switch, you need to worry little. Bosot.asio supports both synchronous and asynchronous programming. They are very different; you need to choose one of them early, because the transitions between them are very complex and error-prone. If you choose to synchronize, you can choose exception handling or error code, from exception handling to error code, only need to add a parameter to the call function (error code). Boost.asio can be used not only for network programming. It also has more features, which makes it more valuable, such as semaphores, timers, and so on. In the next chapter we will delve into the functions and classes used in most boost.asio for network programming. At the same time, we will learn some tips for asynchronous programming.

Boost.asio C + + Network programming translator (6)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.