1.1 Demand Source Currently the maintenance control tool of the XXXXX software is input by the command line, and later because user needs change, it is necessary to provide a remote Telnet port to achieve remote multi-user maintenance. Because it is currently reading the input on the command line through the stream, if the input of the Telnet port is also read through the stream, the current implementation is basically not modified. Also, if this function is realized, all the tools to be implemented in the future will be equally related to file input, standard input, network data; can be output to files, standard output, network, and applications can be used in the same way. widely.
1.1 C stream
The input and output of the C stream is always implemented by a buffer. See below
The relationship between flow and buffer is maintained by Basic_ios:
Template
Class Basic_ios: public ios_base {
PUBLIC:
. . .
Basic_StreamBuf
Basic_StreamBuf
}
A variety of different types of buffers are inherited from Basic_StreamBuf, and Basic_StreamBuf provides some virtual functions, such as processing buffer overflow and overflowing functions, and clears the function of buffer overflow and underflow. If we have to provide new buffering strategies and new input destination or output destination, a correct starting point is to inherit your new class from Basic_StreamBuf to reload the necessary virtual functions. Then this new streambuf can be used with any existing stream, such as Stringstream, Strstream, etc.
In the simplest case, if we ask I / O operations to be uncomfortable, only need to overload the Basic_StreamBuf's overflow and underflow virtual function, if we have its own buffer, it is generally to overload a clear buffer. The virtual function, which sends the contents of the buffer to the actual destination when the flow is turned off or when the flush operation is displayed.
1.2 Our packaging method
The buffer we need should read data from the socket and send the input via Socket. In order to implement the versatility of the buffer, we cannot separate the buffers and sockets of the Socket. Slightly abstract, the buffer we need relies on such an interface:
Struct readwriter {
INTRE (CHAR * S, INT LEN); // Complete the function of reading data from the actual destination, incoming the buffer of the saved data, the buffer length is LEN, returns the actual read data length
INT WRITE (const char * s, int LEN); // Complete the function of transmitting data to the actual destination, the data that needs to be transmitted in the buffer of the length LEN, returns the length of the transmitted data.
}
Want to implement the read and write operation of Socket, you can do a simple adaptation process, this adaptation process is not mentioned in this article. Our buffer relies on this interface, of course, because StreamBuf in the standard library is implemented using templates, so the above interface is input as a template parameter.
In addition, the data written to our streambuf should not be read from streambuf, which is different from the other StreamBUF input output in the standard library. This means that we need to maintain two buffers, read buffers to save data obtained from READWRITER, and write buffers to save data written to Readwriter. Thus, the overflow of the buffer in the previous buffer should be the case where the buffer is full; the buffer should be the case where the buffer data is empty; the operation of the emptying buffer (SYNC) should be directed to the write buffer In terms of. According to the previous analysis, we can get the following definition:
Template
Class Streambufadaptor: Public Basic_StringBuf
{
RW & _RW;
PUBLIC:
Typedef chart char_type;
Typedef traits :: int_type int_type;
Typedef Traits :: POS_TYPE POS_TYPE
Typedef Traits :: OFF_TYPE OFF_TYPE;
Typedef Traits Traits_Type;
StreamBufadaptor (RW & RW): _RW (rw) {}
protected:
Virtual int sync ()
{
Calculate the amount of data in the buffer, write these data into _RW
Reset the header to the buffer to the buffer
}
Virtual Int_Type overflow (Chart C)
{
First call the SYNC virtual function, empty the contents in the buffer, and reset the write pointer
Save the input C to buffer
}
Virtual int_type underflow ()
{
Read data according to the size of the read buffer _rw.read function
}
}
Complete implementation See the definition in the attachment
1.3 StreamBufadaptor's way of use
As mentioned earlier, streambuf and stream are connected in the Basic_ios. Because many streams, such as STRSTREAM, STRINGSTREAM, etc. hide the implementation of Basic_ios <> :: Rdbuf (streambuf *), we must replace an actual stream to make a Basic_ios for an operation. See the example below:
Stringstream strout;
RW rw; // rw is a read and write class you implemented
Streambufadaptor
Iostream & StreamRef = strout;
StreamRef.rdbuf (& mybuf);
Strout << "this is a test" << ...
String S;
Strout >> S;
.
The above use method is cumbersome, I hope there is a simple and easy way to replace it. Borrowing the implementation and way of use of ScopeGuard, there is a solution below:
1. Define a streamadaptor class, complete the call of RDBUF in its constructor, recovery in the destructor
2. Because we don't directly operate the StreamAdaptor class, use ScopeGuard to define macros.
3. Because the user should only see the two interfaces, one is the stream of the input and output interface, one is the actual read and write class of the underlying data, as for the intermediate streambufadaptor can be hidden. See attachments for specific implementation details.
Finally, our call is as follows:
Stringstream strout;
RW rw; // rw is a read and write class you implemented
// streambufadaptor
// iostream & streamref = strout;
//streamRef.rdbuf (&MYBUF);
Stream_Adpator (Strout, RW); // This is all of our implementation flow and socket connection
Strout << "this is a test" << ...
String S;
Strout >> S;
.
1.4 Accessories (Complete Realization)
/ ****************************** DEPT: TEST *** Author: htj ******** ***************************** / # include
IF (Traits :: EQ_INT_TYPE (C, Traits :: EOF ())) Return Traits :: Not_eof (C); Else {IF (PPTR () == 0) Init_out_buf (); Return SPUTC (C);}} Virtual INT_TYPE Underflow () {IF ((Basic_StreamBuf