Click here to Skip to main content
Click here to Skip to main content

Fast Ring Buffer for Incoming Winsock Textual Data

, 14 May 2002
Rate this:
Please Sign up or sign in to vote.
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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Larry Antram
Web Developer
United States United States
I'm a former Microsoft employee (ack!) who was the Primary Developer of Microsoft Scenes 1.0 and the Lead Developer of Microsoft Scenes 2.0. While there, I also worked on the TrueType Font Embedding Library, wrote the Win32 GetUnicodeCodepoints API (which mysteriously disappeared into the void), worked on Font Assistant, Word Assistant, and Office Assistant (long forgotten applications), and did pioneering work on what would eventually become Microsoft PictureIt!.
 
In 1995, I left Microsoft and founded Stardust Software which I currently own and operate.
 
My programming experience is primarily in the C/C++/MFC world, secondarily in ASP/JavaScript... with a little COM/ATL sprinkled on top.
 
Or something like all of that... Smile | :)

Comments and Discussions

 
GeneralFix for WriteBinary PinmemberET200520-Mar-08 5:03 
GeneralThis code is buggy PinmemberET200520-Mar-08 5:54 
GeneralNot only MFC has CString PinmemberET200520-Mar-08 2:40 
GeneralProblem with GetMaxWriteSize + WriteBinary PinmemberElDoro14-Mar-08 9:52 
It seems that there is a problem with GetMaxWriteSize / WriteBinary.
 
It fails if you call GetMaxWriteSize() to get available space and then call WriteBinary to put exactly this amount of data in the buffer.
I suggest the following two fixes:
 

int GetMaxWriteSize()
{
if( m_pBuf )
{
if( m_iReadPtr == m_iWritePtr )
return m_nBufSize - 1; // NOTE -1
if( m_iWritePtr < m_iReadPtr )
return m_iReadPtr - m_iWritePtr - 1; // NOTE -1
if( m_iWritePtr > m_iReadPtr )
return (m_nBufSize-m_iWritePtr)+m_iReadPtr - 1; // NOTE -1
}
return 0;
}

 
and
 

BOOL WriteBinary( char * pBuf, int nBufLen )
{
BOOL bResult = FALSE;
{
if( nBufLen <= GetMaxWriteSize() ) // NOTE <=
....

GeneralRe: Problem with GetMaxWriteSize + WriteBinary PinmemberET200520-Mar-08 5:07 
GeneralFix for ReadBinary PinsussAnonymous7-Dec-04 5:08 
Generaluserful for server Pinmembermatrowang26-Jul-04 18:03 
GeneralFixes to Destroy() method PinmemberAnonymous13-Jun-02 8:04 
GeneralInteresting Article PinmemberNick Parker15-May-02 2:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411023.1 | Last Updated 15 May 2002
Article Copyright 2002 by Larry Antram
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid