Example 7 of Muduo network programming: "serial parallel conversion" connecting to the server and its Automated Testing

Source: Internet
Author: User

Functional requirements
This connection server aggregates Multiple customer connections into an internal TCP connection, which acts as a "data string and conversion", allowing the backend Logic Server to focus on business processing, there is no need to consider the concurrency of multiple connections. The system diagram is as follows:

The function of this connection server is similar to that of the data selector (multiplexer) in a digital circuit, so I name it multiplexer. (In fact, IO-Multiplexing also means this, so that a thread-of-control can selectively process multiple IO file descriptors .)

 

(Obtained from wikipedia, public domain copyright)

Implementation
The functional requirements of Multiplexer are not complex. It is nothing more than switching data between backend connection and client connections. Specifically, it mainly handles four types of events:

Assign a new integer id to each new client connection. If the id is used up, the new connection is disconnected (the maximum number of connections can be controlled by controlling the number of IDS ). In addition, to avoid the excessive reuse of IDS (which may lead to backend calls), multiplexer uses queue to manage free IDs. Each time the IDs are obtained from the queue header, they are put back at the end of the queue.
When the client connection arrives or is disconnected, a notification is sent to the backend. OnClientConnection () http://code.google.com/p/muduo/source/browse/tags/0.2.0/examples/multiplexer/multiplexer_simple.cc#54
When receiving data from client connection, send the data together with the connection id to backend. OnClientMessage () http://code.google.com/p/muduo/source/browse/tags/0.2.0/examples/multiplexer/multiplexer_simple.cc#117
When receiving data from the backend connection, identify the client connection to which the data is sent and perform the corresponding forwarding operation. OnBackendMessage () http://code.google.com/p/muduo/source/browse/tags/0.2.0/examples/multiplexer/multiplexer_simple.cc#194
If the backend connection is disconnected, disconnect all client connections (assuming the client will automatically retry ). OnBackendConnection () http://code.google.com/p/muduo/source/browse/tags/0.2.0/examples/multiplexer/multiplexer_simple.cc#162
As shown in the preceding figure, the multiplexer function is quite similar to that of proxy. Multiplexer_simple.cc is a thread version implementation. With muduo's io-multiplexing feature, it can easily process multiple concurrent connections.

There are two points worth noting during implementation:

How to store the TcpConnection id? When receiving data from the backend, how do I find the corresponding client connection based on the id? How do I know the id of the data received from client connection?
The first problem is better solved. Use std: map <int, TcpConnectionPtr> clientConns _; To save the ing from id to client connection.

The second problem can be solved in a similar way, but I would like to introduce the context Function of muduo: net: TcpConnection. Each TcpConnection has a boost: any member, which can be controlled by the customer's code (get/set). The Code is as follows. This boost: any is the context of TcpConnection, it can be used to save any data bound to the connection (such as the connection id, the arrival time of the last data of the connection, and the name of the user represented by the connection ). In this way, the customer code can attach its own State without inheriting TcpConnection, and does not need TcpConnectionFactory (if inheritance is allowed, the factory must be injected to TcpServer ).

Class TcpConnection: public boost: enable_shared_from_this,
Boost: noncopyable
{
Public:

Void setContext (const boost: any & context)
{Context _ = context ;}

Boost: any & getContext ()
{Return context _;}

Const boost: any & getContext () const
{Return context _;}

//...

Private:
//...
Boost: any context _;
};

Typedef boost: shared_ptr TcpConnectionPtr;
For Multiplexer, call conn-> setContext (id) in onClientConnection () to save the id to the TcpConnection object. OnClientMessage () obtains the id from the TcpConnection object and sends it to the backend together with the data. The complete implementation is as follows:

Void onClientMessage (const TcpConnectionPtr & conn, Buffer * buf, Timestamp)
{
If (! Conn-> getContext (). empty ())
{
Int id = boost: any_cast (conn-> getContext ());
SendBackendBuffer (id, buf );
}
Else
{
Buf-> retrieveAll ();
}
}
How to manage the lifecycle of TcpConnection? Since Client Connection is dynamically created and destroyed, it is entirely determined by the customer to generate and destroy it. How can we ensure that the TcpConnection object is still alive when the backend wants to send data to it? The solution is to use reference counting. Of course, you don't need to write it yourself. Use boost: shared_ptr. TcpConnection is the only object in muduo that uses shared_ptr by default to manage the life cycle, which is determined by the nature of its dynamic life cycle. For more information, see Chen Shuo's thread-safe object callback in C ++ when the Destructor encounters multithreading.
Multiplexer is a binary protocol. How can we test it?

Automated Testing
Multiplexer is the first network program with non-trivial business logic in the muduo network programming example. According to Chen Shuo's idea in "Automated regression testing of Distributed Programs, I wrote test harness for it. Code see http://code.google.com/p/muduo/source/browse/trunk/examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer

This Test harness is written in Java and uses the Netty library. This test harness should act as clients and backend, that is, both actively initiate connections and passively accept connections. The structure is as follows:

 

Test harness aggregates various events into a blocking queue to facilitate the compilation of test cases. Test case is used to manipulate test harness, initiate a connection, send data, and check the received data. For example, one of the following is test case.

Http://code.google.com/p/muduo/source/browse/trunk/examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/testcase/TestOneClientSend.java

Several test cases are written in java. If necessary, you can also write them in Groovy. This allows you to add test cases at any time without restarting test harness. For specific practices, see Chen Shuo's implementation of the mobile offline billing system for "Family Pass".

Future improvements
With this automated test harness, we can easily and securely modify (or even redesign) multiplexer. For example

Added the "backend sending command to disconnect the client connection" function. With automated testing, this new function can be tested independently (by developers) without the real backend.
Use multiple threads to rewrite Multiplexer. With automated regression testing, we don't have to worry about disrupting the original functions, so we can rewrite them with confidence. In addition, because test harness is an external test, not a unit test, test cases is not required when the multiplexer is rewritten, which ensures the stability of the test. In addition, this test harness is slightly improved and can be used for stress test.

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.