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

Source: Internet
Author: User
ArticleDirectory
    • Future improvements

Muduo network programming example 7: connecting to the server and its Automated Testing

Chen Shuo (giantchen_at_gmail)

Blog.csdn.net/solstice t.sina.com.cn/giantchen

This is the seventh article in The muduo network programming example series.

Muduo full article list: http://blog.csdn.net/Solstice/category/779646.aspx

This article describes how to use test harness to test a network service with internal logic.Program.

TheCodeSee http://code.google.com/p/muduo/source/browse/trunk/examples/multiplexer

: Http://muduo.googlecode.com/files/muduo-0.2.0-alpha.tar.gz sha1 checksum: 75a09a82f96b583001086e95105c679e64c95715

In his blog, Yun Feng mentioned the functional requirements for connecting online games to servers (search for "hands-on projects"). I initially met these requirements using C ++, and compiled the supporting automated test harness for it as an example of the muduo network library.

Note: The Code presented in this article only meets the basic functional requirements, without considering the security and performance optimization. It is not suitable for online game connection servers that are truly running on the public network.

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.
    • send a notification to backend when the client connection arrives or is disconnected. 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 clients (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 single-threaded 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 'd like to introduce it hereContext 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 <tcpconnection>, boost: noncopyable {public: voidSetcontext(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 <tcpconnection> 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 <int> (Conn-> getcontext ());Sendbackendbuffer (ID, Buf);} else {Buf-> retrieveall ();}}
    • How to manage the life cycle 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. In addition, the startup sequence of test harness and multiplexer is arbitrary. Read the code for how to do this. 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, the test harness can be improved slightly by using stress testing, which can be used to verify the correctness of multi-threaded multiplexer and improve the efficiency compared with the single-threaded version.

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.