For Iperf source parsing, I was based on the 2.0.5 version in Windows execution of the situation analysis, advocated to start first through the simple modification of the source code to enable it to run in the local compiler, so that you can print out some intermediate information, for understanding the logic of the source code, The process of program implementation can play a multiplier effect.
Iperf is mainly divided into the following modules:
- option parameter processing;
- Thread encapsulation and role playing;
- Four threading modes (or roles):
- Client thread;
- Service thread;
- The speaker thread;
- Listener thread.
- Socket option settings and extraction;
- Chain list and array of encapsulation and maintenance;
- Handle the encapsulation of multiple concurrent condition condition variables;
- Time stamp encapsulation;
- Created and run as a background service under Windows.
The following is illustrated for each module as much as possible:
Handling of option Parameters:
As a command-line console application, the primary consideration is the handling of input parameter command-line options, and if a simple application can be resolved directly through the Case-switch or if condition statement, but once it is large, the console application that implements the content is more complex, such as Iperf, or the processing method is relatively clumsy, in terms of performance, logic processing and so on.
For the processing of the option parameters, a getopt file for the gun used by Iperf, which already has the header file under Linux, and after Windows needs to import the header and implementation files, and after adding the files, it is necessary to process some long options and short-choice strings in the file. Since this is a requirement of your own definition, the logic for handling option parameters is certain, but what you want to use as reasonable options and parameters and operands, those that are illegal and unrecognized, is a procedure that needs to be judged, so a process of initialization is required. Later in the process of using invoke the corresponding interface to the main function passed in the args and argv[] as input parameters to deal with, more about the options parameters of processing, you can look at the article, or search the Web itself.
The main module of the program is the generation, operation and destruction of the role thread, other modules including timestamp, condition variables, maintenance of the linked list are all for this service, so it is intended to talk about the other modules and then analyze the different types of threads.
Package and settings for socket options:
Say the socket option before you need to mention the generation of sockets, IPERF socket socket generation defines a macro called Win32socket, which calls WSASocket, and the properties and protocol type of the socket are defined by the Wsaprotocol_ Info type static function, and the function is passed as input parameter to wassocket implementation.
There is only one function named Setsocketoptions in PerfSocket.cpp that is used to set the value of the socket option, which includes setting the TCP sliding window size (the Setsock_tcp_windowsize function in another named TCP _window_size.c files), set up congestion control, set multicast, set the IP service type (this is rarely used), set the maximum packet size (SETSOCK_TCP_MSS function is implemented in the SOCKETS.C file), set non-latency, and so on. Of course, in addition to setting socket options, there are functions that get the appropriate options, such as Getsock_tcp_windowsize and GETSOCK_TCP_MSS.
In the socketaddr.c file, Iperf defines a series of functions named in the "Socketaddr_ function function" format, which determines whether IPV6 is supported by a macro condition, and defines the socket address structure that is obtained by IP address or converted to a peer. Turn the network sequence into dotted decimal, get and set the port value, etc., around the defined iperf_sockaddr type (IPV4 under the sockaddr_in type, IPV6 under Sockaddr_storage) to determine whether the socket address is the same, and so on.
Maintenance and encapsulation of linked lists and arrays:
Iperf creates several different types of linked lists and arrays in the implementation: At the beginning of the line threads, the report uses the report header linked list, the listener thread maintains the client chain list, immediately after the routing type reporter header of the packet array, An array of transmission information maintained by multiple groups of report headers on the server side and multiple concurrent clients. Specifically, the next step is to describe in detail, the List.cpp package for the Iperf_listentry type linked list of additions and deletions and destruction operations, and the linked list is only used by listeners to store and maintain the connected client information, there is no use for it.
To handle the encapsulation of multiple concurrent condition condition variables:
Condition is the structure of Iperf's own encapsulation, the variable mcondition is the handle of the event kernel object, and the variable Mmutex the handle of the mutex.
Condition_initialize (Cond): Creates a mutex that initializes the trigger state and assigns the returned handle value to Mmutex, creating a manual reset event initialized to the non-triggering state and assigning the returned handle value to Mcondition;
Condition_destroy (Cond): Destroys the event kernel object and mutex through the handle values of mcondition and Mmutex;
Condition_lock (Cond) = = Mutex_lock (&cond.mmutex) = = WaitForSingleObject (Cond.mmutex, INFINITE)
Condition_unlock (Cond) = = Mutex_unlock (&cond.mmutex) = = ReleaseMutex (Cond.mmutex)
Condition_wait (Cond): First release the mutex, then block the permanent wait for the event to occur, and then wait for the mutex amount;
Condition_timedwait (Cond): First release the mutex, then block for a certain amount of time to wait for the event to occur, and then wait for the mutex;
Condition_signal (Cond): Because it is a manual reset event, when it is called, all the threads that are waiting for the event become scheduled; First you need to understand the difference between setevent and pulseevent, because it is a manual reset event. This is different for two functions, the automatic reset event type, after the event has been waiting to be received after the receipt will automatically reset to the non-triggered state, you can see the contents of the 9th chapter of Windows core Programming, also describes the role of the signalobjectandwait function.
The macro defined by the condition condition variable is not well understood during use, because it is easy to confuse the wait event with the acquisition mutex when it is called, and when the mutex is released and then waits for the event to occur, it is hard to wait for the event to take ownership of the mutex. So the writer in each wait and every entry and subsequent exit condition add the corresponding debug output, this may be easy to understand the point, because the relationship between time, can only put it back to chew understand, but in the process of output can actually find its role, For example, the reporter in the case of no comment waiting for output content.
Time stamp:
It is estimated that in order to unify with UNIX, Iperf does not call API usage time directly on Win32, but encapsulates gettimeofday itself. The time of the UTC format obtained by Getsystemtimeasfiletime is converted to the time of the Unix epoch and returned by the Timeval type, where several special numbers are used in the implementation function, which is explained clearly in the comment on the source code line and is no longer described here;
Timestamp This class has only one member variable of type Timeval, the member function includes getting the current time, adding and reducing time, comparing two time successively, etc., it is easier to understand.
Timestamps are used to assign values to each sending packet during the data transfer process, indicating when the packet was sent, and in the condition that the-I option is used to calculate the time to print the report every time, by comparing the time that the report will be printed and the timestamp of the most recent sending package. Determines whether to print the bandwidth sent during this time and the amount of data sent and the time period sent.
Run as a background service:
Only for the server side, and when running as a background service, the-o filename option parameter can play a role, but also to join others to implement the file, a little look at, is through the Scmanager API to create and execute the service, this later have time to seriously study, You can consider that you can reuse some of the later projects.
This article is about here, the next article began to explain the thread and role, that is, in conjunction with the thread to explain the client, the server, the reporter, the listener's execution process, for the moment only in TCP mode, UDP follow-up to explain, of course, understand the TCP mode of operation logic, believe that the UDP mode is not difficult to understand.
iperf--Network test Tool Introduction and source code Analysis (2)