Click here to Skip to main content
15,895,774 members
Articles / Desktop Programming / MFC

Writing Scalable Server Applications using IOCP

Rate me:
Please Sign up or sign in to vote.
4.15/5 (29 votes)
5 Feb 2001 454.2K   9.1K   155  
An article about using I/O Completion Ports and Winsock to write robust and scalable Windows server applications
// Written by Oz Ben Eliezer
// o_be@hotmail.com
// September, 2000

#ifndef __CLIENT_H__		// Sentinels
#define __CLIENT_H__

#define _WIN32_WINNT 0x0500

#include <windows.h>
#include <time.h>

#include "buffer.h"
#include "general.h"
#include "callback.h"

#define IN_BUFFER_SIZE		2048
#define IN_BUFFER_SIZE_INC	2048
#define MAX_IN_BUFFER_SIZE	1048576

#define OUT_BUF_SIZE	4096
#define STATE_DEAD		0
#define	STATE_ACCEPTING	1
#define STATE_CONNECTED	2

struct OVERLAPPED_PLUS : public OVERLAPPED
{
	unsigned int client;
	bool bCtxWrite;
};

class CClient
{
protected:
	CAutoBuffer *out_buffer;	// Data that is to be sent to client
	unsigned long nWritten;
	char *actual_in_buf;
	char *actual_out_buf;
	OVERLAPPED_PLUS ovIn;		// Used in WSARead() calls
	OVERLAPPED_PLUS ovOut;		// Used in WSASend() calls
	char *end_in_buf_pos;
	char *start_in_buf_pos;
	CRITICAL_SECTION csInUse;
	sockaddr_in local;
	sockaddr_in peer;
	int nInBufferSize;
	tagPacket *p;				// Packet for processing
	time_t ltime;

	__forceinline void InitializeInUse()
	{
		InitializeCriticalSection(&csInUse);
	}

	__forceinline void DeleteInUse()
	{
		DeleteCriticalSection(&csInUse);
	}

	__forceinline void Timestamp()
	{
		time(&ltime);
	}

	__forceinline int SecondsElapsed()
	{
		time_t timenow;
		time(&timenow);
		return timenow - ltime;
	}

public:
	static int nID;
	int nSpecificID;

	__forceinline void EnterInUse()
	{
		EnterCriticalSection(&csInUse);
	}

	__forceinline void LeaveInUse()
	{
		LeaveCriticalSection(&csInUse);
	}

	SOCKET s;					// Socket used to communicate with client
	int nState;					// Current state of instance
	long bPendingWrite;			// Is there data pending to be sent?
	long bMayWrite;				// Is it possible to send data now?
	unsigned long nRead;

	CClient();
	~CClient();
	void Init();				// Attach to a new client
	void Close();				// Detach from a client
	bool Write(tagPacket *p);	// Add a packet to output buffer
	bool Read(tagPacket *p);	// Retrieve a packet from input buffer
	bool NetWrite();			// Do actual send
	bool IssueNetRead();		// Do actual receive
	void SetRead(int nNewlyRead);
	__forceinline void ShiftState()	// Move from ACCEPTING to CONNECTED state
	{
		int locallen, remotelen;
		sockaddr_in *plocal = 0, *premote = 0;

		if (nState == STATE_ACCEPTING)
		{
			GetAcceptExSockaddrs(&actual_in_buf[0],
				IN_BUFFER_SIZE,
				sizeof(sockaddr_in) + 16,
				sizeof(sockaddr_in) + 16,
				(sockaddr **)&plocal,
				&locallen,
				(sockaddr **)&premote,
				&remotelen);

			memcpy(&local, plocal, sizeof(sockaddr_in));
			memcpy(&peer, premote, sizeof(sockaddr_in));


			if (BindIoCompletionCallback((HANDLE)s, DoneIO, 0))
			{
				nState = STATE_CONNECTED;
				Timestamp();
				printf("\nConnected client, ID# %d", nSpecificID);
			}
		}
	}

	__forceinline bool Read()
	{
		return Read(p);
	}

	__forceinline int ProcessPacket()
	{
		return ProcessPacket(p);
	}

	virtual int ProcessPacket(tagPacket *p) = 0;		// Process a packet.
	virtual void CreateInvalidPacket(tagPacket *p) = 0;	// Invalidate packet.
	virtual void Maintenance() = 0;						// Maintenance
};

#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions