Fast Ring Buffer for Incoming Winsock Textual Data





4.00/5 (9 votes)
May 15, 2002

87930

1922
A fast ring buffer designed for receiving texual data in a Winsock server application.
Introduction
The CRingBuffer
class was designed to be a fast and convenient way of collecting incoming data from a socket, then retrieving it one text line at a time. It intentionally does no dynamic buffer allocation/deallocation during runtime, so as to avoid memory fragmentation and other issues.
It was created in Visual C++ 6 as part of the creation of separate POP3 and SMTP servers. The entire class is contained in a single header file, and uses CString
in one function (and as such, requires MFC, although it would be trivial to remove that dependency).
The CRingBuffer Interface
// Constructor CRingBuffer(); // Destructor virtual ~CRingBuffer(); // Initializes the ring buffer for use. BOOL Create( int iBufSize ); // Cleans up the ring buffer. void Destroy(); // Returns the amount of data (in bytes) available for reading from the buffer. int GetMaxReadSize(); // Returns the amount of space (in bytes) available for writing into the buffer. int GetMaxWriteSize(); // Writes data into the ring buffer. BOOL WriteBinary( char * pBuf, int nBufLen ); // Reads (and extracts) data from the ring buffer. BOOL ReadBinary( char * pBuf, int nBufLen ); // Peeks at a character at the given position in the ring buffer, without // extracting it. BOOL PeekChar( int iPos, char & ch ); // Determines if the specified character is in the ring buffer, and if so, // returns the index position. BOOL FindChar( char chLookFor, int & riPos ); // Reads a line of text from the buffer, if available. BOOL ReadTextLine( CString & strLine );
How To Use It
As previously mentioned, this class is designed for server applications. It probably has very little use outside of that scope. That said, here is an extremely simplified example of how to use it.
#include "RingBuffer.h" // // Initialization // using namespace Stardust; #define INCOMING_RING_BUFFER_SIZE (1024*16) // or whatever CRingBuffer m_ringbuf; m_ringbuf.Create( INCOMING_RING_BUFFER_SIZE + 1 ); char m_chInBuf[ INCOMING_BUFFER_SIZE + 1 ]; ... // // Then later, upon receiving data... // int iNumberOfBytesRead = 0; while( READ_INCOMING(m_chInBuf,INCOMING_BUFFER_SIZE,&iNumberOfBytesRead,0) && iNumberOfBytesRead > 0 ) { // add incoming data to the ring buffer m_ringbuf.WriteBinary(m_chInBuf,iNumberOfBytesRead); // pull it back out one line at a time, and distribute it CString strLine; while( m_ringbuf.ReadTextLine(strLine) ) { strLine.TrimRight("\r\n"); if( !ON_INCOMING( strLine ) ) return FALSE; } } // Fall out, until more incoming data is available...
In the above example, READ_INCOMING
and ON_INCOMING
are placeholders for functions that read and accept incoming data respectively. READ_INCOMING
reads raw incoming data from the socket while ON_INCOMING
accepts incoming data from the socket, one line at a time.