PDA

View Full Version : Network Class proposal for OpenEQ


MOG
12-19-2004, 09:24 AM
// XSocket.cpp: implementation of the XSocket class.
//
//////////////////////////////////////////////////////////////////////

#include "XSocket.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

// iBlockLimit - queue size for unsent data queue

// it's circular queue, where m_sHead and m_sTail indicates

// real head index and real tail index

// note that maximum value is DEF_XSOCKBLOCKLIMIT and it's used too!!!
XSocket::XSocket(HWND hWnd, int iBlockLimit)
{
register int i;

m_cType = NULL;
m_pRcvBuffer = NULL;
m_pSndBuffer = NULL;
m_Sock = INVALID_SOCKET;
m_dwBufferSize = 0;

m_cStatus = DEF_XSOCKSTATUS_READINGHEADER;
m_dwReadSize = 3;
m_dwTotalReadSize = 0;

for (i = 0; i < DEF_XSOCKBLOCKLIMIT; i++) {
m_iUnsentDataSize[i] = 0;
m_pUnsentDataList[i] = NULL;
}

m_sHead = 0;
m_sTail = 0;

m_WSAErr = NULL;

m_hWnd = hWnd;
m_bIsAvailable = FALSE;
m_bIsWriteEnabled = FALSE;

m_iBlockLimit = iBlockLimit;
}

XSocket::~XSocket()
{
register int i;

if (m_pRcvBuffer != NULL) delete[] m_pRcvBuffer;
if (m_pSndBuffer != NULL) delete[] m_pSndBuffer;

for (i = 0; i < DEF_XSOCKBLOCKLIMIT; i++)
if (m_pUnsentDataList[i] != NULL) delete[] m_pUnsentDataList[i];

_CloseConn();
}

BOOL XSocket::bInitBufferSize(DWORD dwBufferSize)
{
if (m_pRcvBuffer != NULL) delete[] m_pRcvBuffer;
if (m_pSndBuffer != NULL) delete[] m_pSndBuffer;

m_pRcvBuffer = new char[dwBufferSize+8];
if (m_pRcvBuffer == NULL) return FALSE;

m_pSndBuffer = new char[dwBufferSize+8];
if (m_pSndBuffer == NULL) return FALSE;

m_dwBufferSize = dwBufferSize;

return TRUE;
}
// dispatcher. for NORMALSOCK only

// event
int XSocket::iOnSocketEvent(WPARAM wParam, LPARAM lParam)
{
int WSAEvent;

if (m_cType != DEF_XSOCK_NORMALSOCK) return DEF_XSOCKEVENT_SOCKETMISMATCH;

if (m_cType == NULL) return DEF_XSOCKEVENT_NOTINITIALIZED;

if ((SOCKET)wParam != m_Sock) return DEF_XSOCKEVENT_SOCKETMISMATCH;
WSAEvent = WSAGETSELECTEVENT(lParam);

switch (WSAEvent) {
case FD_CONNECT:
if (WSAGETSELECTERROR(lParam) != 0) {

if (bConnect(m_pAddr, m_iPortNum, m_uiMsg) == FALSE) return DEF_XSOCKEVENT_SOCKETERROR;

return DEF_XSOCKEVENT_RETRYINGCONNECTION;
}
else {
m_bIsAvailable = TRUE;
return DEF_XSOCKEVENT_CONNECTIONESTABLISH;
}
break;

case FD_READ:
if (WSAGETSELECTERROR(lParam) != 0) {

m_WSAErr = WSAGETSELECTERROR(lParam);
return DEF_XSOCKEVENT_SOCKETERROR;
}
else return _iOnRead();
break;

case FD_WRITE:
m_bIsWriteEnabled = TRUE;
return _iSendUnsentData();
break;

case FD_CLOSE:
m_cType = DEF_XSOCK_SHUTDOWNEDSOCK;
return DEF_XSOCKEVENT_SOCKETCLOSED;
break;
}

return DEF_XSOCKEVENT_UNKNOWN;
}

BOOL XSocket::bBlockConnect(char * pAddr, int iPort, unsigned int uiMsg)
{
SOCKADDR_IN saTemp;
int iRet;
DWORD dwOpt;
struct hostent * hp;


if (m_cType == DEF_XSOCK_LISTENSOCK) return FALSE;
if (m_Sock != INVALID_SOCKET) closesocket(m_Sock);

m_Sock = socket(AF_INET, SOCK_STREAM, 0);
if (m_Sock == INVALID_SOCKET)
return FALSE;

memset(&saTemp,0,sizeof(saTemp));
hp = gethostbyname(pAddr);
if (hp) {
memcpy(&(saTemp.sin_addr),hp->h_addr, hp->h_length);
saTemp.sin_family = hp->h_addrtype;
saTemp.sin_port = htons(iPort);
}
else {
return FALSE;
}

iRet = connect(m_Sock, (struct sockaddr *) &saTemp, sizeof(saTemp));
if (iRet == SOCKET_ERROR) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
m_WSAErr = WSAGetLastError();
return FALSE;
}
}


dwOpt = 8192*5;
setsockopt(m_Sock, SOL_SOCKET, SO_RCVBUF, (const char FAR *)&dwOpt, sizeof(dwOpt));
setsockopt(m_Sock, SOL_SOCKET, SO_SNDBUF, (const char FAR *)&dwOpt, sizeof(dwOpt));

strcpy(m_pAddr, pAddr);
m_iPortNum = iPort;

m_uiMsg = uiMsg;
m_cType = DEF_XSOCK_NORMALSOCK;

return TRUE;
}

// Create socket and connect it to pAddr and iPort
BOOL XSocket::bConnect(char * pAddr, int iPort, unsigned int uiMsg)
{
SOCKADDR_IN saTemp;
u_long arg;
int iRet;
DWORD dwOpt;


if (m_cType == DEF_XSOCK_LISTENSOCK) return FALSE;
if (m_Sock != INVALID_SOCKET) closesocket(m_Sock);

m_Sock = socket(AF_INET, SOCK_STREAM, 0);
if (m_Sock == INVALID_SOCKET)
return FALSE;


arg = 1;


memset(&saTemp,0,sizeof(saTemp));
saTemp.sin_family = AF_INET;
saTemp.sin_addr.s_addr = inet_addr(pAddr);
saTemp.sin_port = htons(iPort);

WSAAsyncSelect(m_Sock, m_hWnd, uiMsg, FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE);

iRet = connect(m_Sock, (struct sockaddr *) &saTemp, sizeof(saTemp));
if (iRet == SOCKET_ERROR) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
m_WSAErr = WSAGetLastError();
return FALSE;
}
}



dwOpt = 8192*5;
setsockopt(m_Sock, SOL_SOCKET, SO_RCVBUF, (const char FAR *)&dwOpt, sizeof(dwOpt));
setsockopt(m_Sock, SOL_SOCKET, SO_SNDBUF, (const char FAR *)&dwOpt, sizeof(dwOpt));

strcpy(m_pAddr, pAddr);
m_iPortNum = iPort;

m_uiMsg = uiMsg;
m_cType = DEF_XSOCK_NORMALSOCK;

return TRUE;
}

// The socket can be in two major states:

// - READINGHEADER

// - READINGBODY

// First byte in header: xor-chipher key

// 2nd and 3rd - 2-byte: size of body

//
int XSocket::_iOnRead()
{
int iRet, WSAErr;
WORD * wp;

if (m_cStatus == DEF_XSOCKSTATUS_READINGHEADER) {

iRet = recv(m_Sock, (char *)(m_pRcvBuffer + m_dwTotalReadSize), m_dwReadSize, 0);

if (iRet == SOCKET_ERROR) {
WSAErr = WSAGetLastError();
if (WSAErr != WSAEWOULDBLOCK) {
m_WSAErr = WSAErr;
return DEF_XSOCKEVENT_SOCKETERROR;
}
else return DEF_XSOCKEVENT_BLOCK;
}
else
if (iRet == 0) {

m_cType = DEF_XSOCK_SHUTDOWNEDSOCK;
return DEF_XSOCKEVENT_SOCKETCLOSED;
}

m_dwReadSize -= iRet;
m_dwTotalReadSize += iRet;

if (m_dwReadSize == 0) {

m_cStatus = DEF_XSOCKSTATUS_READINGBODY;

wp = (WORD *)(m_pRcvBuffer + 1);
m_dwReadSize = (int)(*wp - 3);

if (m_dwReadSize == 0) {

m_cStatus = DEF_XSOCKSTATUS_READINGHEADER;
m_dwReadSize = 3;
m_dwTotalReadSize = 0;
return DEF_XSOCKEVENT_READCOMPLETE;
}
else
if (m_dwReadSize > m_dwBufferSize) {
m_cStatus = DEF_XSOCKSTATUS_READINGHEADER;
m_dwReadSize = 3;
m_dwTotalReadSize = 0;
return DEF_XSOCKEVENT_MSGSIZETOOLARGE;
}
}
return DEF_XSOCKEVENT_ONREAD;
}
else
if (m_cStatus == DEF_XSOCKSTATUS_READINGBODY) {

iRet = recv(m_Sock, (char *)(m_pRcvBuffer + m_dwTotalReadSize), m_dwReadSize, 0);

if (iRet == SOCKET_ERROR) {
WSAErr = WSAGetLastError();
if (WSAErr != WSAEWOULDBLOCK) {
m_WSAErr = WSAErr;
return DEF_XSOCKEVENT_SOCKETERROR;
}
else return DEF_XSOCKEVENT_BLOCK;
}
else
if (iRet == 0) {

m_cType = DEF_XSOCK_SHUTDOWNEDSOCK;
return DEF_XSOCKEVENT_SOCKETCLOSED;
}

m_dwReadSize -= iRet;
m_dwTotalReadSize += iRet;

if (m_dwReadSize == 0) {

m_cStatus = DEF_XSOCKSTATUS_READINGHEADER;
m_dwReadSize = 3;
m_dwTotalReadSize = 0;
}
else return DEF_XSOCKEVENT_ONREAD;
}


return DEF_XSOCKEVENT_READCOMPLETE;
}


// Try to send data. if it's impossible, like, there's other data waiting

// before this one, or socket was blocked

// - attempt to place it into waiting queue

// - return result of this attemption

// if the data was really sent, then return their len
int XSocket::_iSend(char * cData, int iSize, BOOL bSaveFlag)
{
int iOutLen, iRet, WSAErr;

if (m_pUnsentDataList[m_sHead] != NULL) {
if (bSaveFlag == TRUE) {

iRet = _iRegisterUnsentData(cData, iSize);
switch (iRet) {
case -1:

return DEF_XSOCKEVENT_CRITICALERROR;
case 0:

return DEF_XSOCKEVENT_QUENEFULL;
case 1:

break;
}
return DEF_XSOCKEVENT_BLOCK;
}
else return 0;
}

iOutLen = 0;
while (iOutLen < iSize) {

iRet = send(m_Sock, (cData + iOutLen), iSize - iOutLen, 0);

if (iRet == SOCKET_ERROR) {
WSAErr = WSAGetLastError();
if (WSAErr != WSAEWOULDBLOCK) {

m_WSAErr = WSAErr;
return DEF_XSOCKEVENT_SOCKETERROR;
}
else {

if (bSaveFlag == TRUE) {
iRet = _iRegisterUnsentData((cData + iOutLen), (iSize - iOutLen));
switch (iRet) {
case -1:

return DEF_XSOCKEVENT_CRITICALERROR;
break;
case 0:

return DEF_XSOCKEVENT_QUENEFULL;
break;
case 1:

break;
}
}
return DEF_XSOCKEVENT_BLOCK;
}
} else iOutLen += iRet;

}

return iOutLen;
}


// Try to send as much data as possible

// (whole iSize or less if blocking or error)

int XSocket::_iSend_ForInternalUse(char * cData, int iSize)
{
int iOutLen, iRet, WSAErr;

iOutLen = 0;
while (iOutLen < iSize) {

iRet = send(m_Sock, (cData + iOutLen), iSize - iOutLen, 0);

if (iRet == SOCKET_ERROR) {
WSAErr = WSAGetLastError();
if (WSAErr != WSAEWOULDBLOCK) {

m_WSAErr = WSAErr;
return DEF_XSOCKEVENT_SOCKETERROR;
}
else {

return iOutLen;
}
} else iOutLen += iRet;
}

return iOutLen;
}


// place data in queue if we can't send it immediately

int XSocket::_iRegisterUnsentData(char * cData, int iSize)
{
if (m_pUnsentDataList[m_sTail] != NULL) return 0;

m_pUnsentDataList[m_sTail] = new char[iSize];
if (m_pUnsentDataList[m_sTail] == NULL) return -1;


memcpy(m_pUnsentDataList[m_sTail], cData, iSize);
m_iUnsentDataSize[m_sTail] = iSize;


m_sTail++;
//if (m_sTail >= DEF_XSOCKBLOCKLIMIT) m_sTail = 0;
if (m_sTail >= m_iBlockLimit) m_sTail = 0;

return 1;
}


// When we know that it's possible to send data (FD_WRITE event)

// try to send as much data from queue as possible
int XSocket::_iSendUnsentData()
{
int iRet;
char * pTemp;


while (m_pUnsentDataList[m_sHead] != NULL) {

iRet = _iSend_ForInternalUse(m_pUnsentDataList[m_sHead], m_iUnsentDataSize[m_sHead]);

if (iRet == m_iUnsentDataSize[m_sHead]) {

delete[] m_pUnsentDataList[m_sHead];
m_pUnsentDataList[m_sHead] = NULL;
m_iUnsentDataSize[m_sHead] = 0;

m_sHead++;
//if (m_sHead >= DEF_XSOCKBLOCKLIMIT) m_sHead = 0;
if (m_sHead >= m_iBlockLimit) m_sHead = 0;
}
else {

if (iRet < 0)
return iRet;


pTemp = new char[m_iUnsentDataSize[m_sHead] - iRet];
memcpy(pTemp, m_pUnsentDataList[m_sHead] + iRet, m_iUnsentDataSize[m_sHead] - iRet);

delete[] m_pUnsentDataList[m_sHead];
m_pUnsentDataList[m_sHead] = pTemp;

return DEF_XSOCKEVENT_UNSENTDATASENDBLOCK;
}
}

return DEF_XSOCKEVENT_UNSENTDATASENDCOMPLETE;
}

// form packet (add header)

// cypher data if possible (cKey != 0)

// and send it

// iRet - 3 means that we return only the length of data which was sent, not

// the length of header added

int XSocket::iSendMsg(char * cData, DWORD dwSize, char cKey)
{
WORD * wp;
int i, iRet;


if (dwSize > m_dwBufferSize) return DEF_XSOCKEVENT_MSGSIZETOOLARGE;


if (m_cType != DEF_XSOCK_NORMALSOCK) return DEF_XSOCKEVENT_SOCKETMISMATCH;

if (m_cType == NULL) return DEF_XSOCKEVENT_NOTINITIALIZED;


m_pSndBuffer[0] = cKey;

wp = (WORD *)(m_pSndBuffer + 1);
*wp = (WORD)(dwSize + 3);

memcpy((char *)(m_pSndBuffer + 3), cData, dwSize);

if (cKey != NULL) {
for (i = 0; i < (int)(dwSize); i++) {
m_pSndBuffer[3+i] += (i ^ cKey);
m_pSndBuffer[3+i] = (char)( m_pSndBuffer[3+i] ^ (cKey ^ (dwSize - i)) );
}
}


if (m_bIsWriteEnabled == FALSE) {
iRet = _iRegisterUnsentData(m_pSndBuffer, dwSize +3);
}
else iRet = _iSend(m_pSndBuffer, dwSize + 3, TRUE);

if (iRet < 0) return iRet;
else return (iRet - 3);
}

// Create listener socket, bind it to pAddr,iPort and call listen with

// maximum 5 connections in internal system query
BOOL XSocket::bListen(char * pAddr, int iPort, unsigned int uiMsg)
{
SOCKADDR_IN saTemp;

if (m_cType != NULL) return FALSE;
if (m_Sock != INVALID_SOCKET) closesocket(m_Sock);

m_Sock = socket(AF_INET, SOCK_STREAM, 0);
if (m_Sock == INVALID_SOCKET)
return FALSE;


memset(&saTemp,0,sizeof(saTemp));
saTemp.sin_family = AF_INET;
saTemp.sin_addr.s_addr = inet_addr(pAddr);
saTemp.sin_port = htons(iPort);
if ( bind(m_Sock, (PSOCKADDR)&saTemp, sizeof(saTemp)) == SOCKET_ERROR) {
closesocket(m_Sock);
return FALSE;
}

if (listen(m_Sock, 5) == SOCKET_ERROR) {
closesocket(m_Sock);
return FALSE;
}

WSAAsyncSelect(m_Sock, m_hWnd, uiMsg, FD_ACCEPT);

m_uiMsg = uiMsg;
m_cType = DEF_XSOCK_LISTENSOCK;

return TRUE;
}
// accept connection (from listener socket)

// newly created socket is placed into pXSock
BOOL XSocket::bAccept(class XSocket * pXSock, unsigned int uiMsg)
{
SOCKET AcceptedSock;
sockaddr Addr;
register int iLength;
DWORD dwOpt;

if (m_cType != DEF_XSOCK_LISTENSOCK) return FALSE;
if (pXSock == NULL) return FALSE;

iLength = sizeof(Addr);

AcceptedSock = accept(m_Sock, (struct sockaddr FAR *)&Addr,(int FAR *)&iLength);
if (AcceptedSock == INVALID_SOCKET)
return FALSE;

pXSock->m_Sock = AcceptedSock;
WSAAsyncSelect(pXSock->m_Sock, m_hWnd, uiMsg, FD_READ | FD_WRITE | FD_CLOSE);


pXSock->m_uiMsg = uiMsg;
pXSock->m_cType = DEF_XSOCK_NORMALSOCK;


dwOpt = 8192*5;
setsockopt(pXSock->m_Sock, SOL_SOCKET, SO_RCVBUF, (const char FAR *)&dwOpt, sizeof(dwOpt));
setsockopt(pXSock->m_Sock, SOL_SOCKET, SO_SNDBUF, (const char FAR *)&dwOpt, sizeof(dwOpt));

return TRUE;
}
// close connection

// shutdown socket for writing

// read all available data from it

// and then close it
void XSocket::_CloseConn()
{
char cTmp[100];
BOOL bFlag = TRUE;
int iRet;

if (m_Sock == INVALID_SOCKET) return; // v1.4

shutdown(m_Sock, 0x01);
while (bFlag == TRUE) {
iRet = recv(m_Sock, cTmp, sizeof(cTmp), 0);
if (iRet == SOCKET_ERROR) bFlag = FALSE;
if (iRet == 0) bFlag = FALSE;
}

closesocket(m_Sock);

m_cType = DEF_XSOCK_SHUTDOWNEDSOCK;
}

// return pointer to packet data received

// decypher it if key is available from this packet
char * XSocket::pGetRcvDataPointer(DWORD * pMsgSize, char * pKey)
{
WORD * wp;
DWORD dwSize;
register int i;
char cKey;

cKey = m_pRcvBuffer[0];
if (pKey != NULL) *pKey = cKey;

wp = (WORD *)(m_pRcvBuffer + 1);
*pMsgSize = (*wp) - 3;
dwSize = (*wp) - 3;


if (cKey != NULL) {
for (i = 0; i < (int)(dwSize); i++) {
m_pRcvBuffer[3+i] = (char)( m_pRcvBuffer[3+i] ^ (cKey ^ (dwSize - i)) );
m_pRcvBuffer[3+i] -= (i ^ cKey);
}
}
return (m_pRcvBuffer + 3);
}

int XSocket::iGetPeerAddress(char * pAddrString)
{
SOCKADDR_IN sockaddr;
int iRet, iLen;

iLen = sizeof(sockaddr);
iRet = getpeername(m_Sock, (struct sockaddr *)&sockaddr, &iLen);
strcpy(pAddrString, (const char *)inet_ntoa(sockaddr.sin_addr));

return iRet;
}

int XSocket::iSendMsgBlockingMode(char *buf,int nbytes)
{
int nleft =0,nwriten = 0 ;

nleft = nbytes;
while (nleft > 0) {
nwriten = send(m_Sock,buf,nleft,0);
if (nwriten < 0){
return nwriten;
}
if (nwriten == 0) break;
nleft -= nwriten;
buf += nwriten ;
}
return (nbytes - nleft);
}

XSocket.cpp

It will only work for the windows version, without changes. But it can be adapted to pure BSD sockets. I appreciate any opinions you might have on my class.
Edit - COMMENTS ADDED

MOG

MOG
12-19-2004, 09:28 AM
XSocket.h follows:

// XSocket.h: interface for the XSocket class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_XSOCKET_H__F9D1BA42_7338_11D2_A8E6_00 001C7030A6__INCLUDED_)
#define AFX_XSOCKET_H__F9D1BA42_7338_11D2_A8E6_00001C7030A 6__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#define _WINSOCK2API_
//#define FD_SETSIZE 2000
#include <windows.h>
#include <windowsx.h>
#include <winsock2.h>
//#include <winsock.h>
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <malloc.h>
#include <winbase.h>

#define DEF_XSOCK_LISTENSOCK 1
#define DEF_XSOCK_NORMALSOCK 2
#define DEF_XSOCK_SHUTDOWNEDSOCK 3

#define DEF_XSOCKSTATUS_READINGHEADER 11
#define DEF_XSOCKSTATUS_READINGBODY 12

#define DEF_XSOCKEVENT_SOCKETMISMATCH -121

#define DEF_XSOCKEVENT_CONNECTIONESTABLISH -122

#define DEF_XSOCKEVENT_RETRYINGCONNECTION -123

#define DEF_XSOCKEVENT_ONREAD -124

#define DEF_XSOCKEVENT_READCOMPLETE -125
#define DEF_XSOCKEVENT_UNKNOWN -126
#define DEF_XSOCKEVENT_SOCKETCLOSED -127

#define DEF_XSOCKEVENT_BLOCK -128

#define DEF_XSOCKEVENT_SOCKETERROR -129

#define DEF_XSOCKEVENT_CRITICALERROR -130

#define DEF_XSOCKEVENT_NOTINITIALIZED -131

#define DEF_XSOCKEVENT_MSGSIZETOOLARGE -132

#define DEF_XSOCKEVENT_CONFIRMCODENOTMATCH -133

#define DEF_XSOCKEVENT_QUENEFULL -134

#define DEF_XSOCKEVENT_UNSENTDATASENDBLOCK -135
#define DEF_XSOCKEVENT_UNSENTDATASENDCOMPLETE -136


#define DEF_XSOCKBLOCKLIMIT 300

class XSocket
{
public:
void * operator new (size_t size)
{
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
};

void operator delete(void * mem)
{
HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, mem);
};
int iSendMsgBlockingMode(char *buf,int nbytes);
int iGetPeerAddress(char * pAddrString);
char * pGetRcvDataPointer(DWORD * pMsgSize, char * pKey = NULL);
BOOL bAccept(class XSocket * pXSock, unsigned int uiMsg);
BOOL bListen(char * pAddr, int iPort, unsigned int uiMsg);

int iSendMsg(char * cData, DWORD dwSize, char cKey = NULL);
BOOL bConnect(char * pAddr, int iPort, unsigned int uiMsg);
BOOL bBlockConnect(char * pAddr, int iPort, unsigned int uiMsg);
int iOnSocketEvent(WPARAM wParam, LPARAM lParam);
BOOL bInitBufferSize(DWORD dwBufferSize);
XSocket(HWND hWnd, int iBlockLimit);
virtual ~XSocket();

int m_WSAErr;
BOOL m_bIsAvailable;
BOOL m_bIsWriteEnabled;

void _CloseConn();

int _iSendUnsentData();
int _iRegisterUnsentData(char * cData, int iSize);
int _iSend(char * cData, int iSize, BOOL bSaveFlag);
int _iSend_ForInternalUse(char * cData, int iSize);
int _iOnRead();

char m_cType;
char * m_pRcvBuffer;
char * m_pSndBuffer;
DWORD m_dwBufferSize;

SOCKET m_Sock;
char m_cStatus;
DWORD m_dwReadSize;
DWORD m_dwTotalReadSize;
char m_pAddr[30];
int m_iPortNum;

char * m_pUnsentDataList[DEF_XSOCKBLOCKLIMIT];
int m_iUnsentDataSize[DEF_XSOCKBLOCKLIMIT];
short m_sHead, m_sTail;

unsigned int m_uiMsg;
HWND m_hWnd;

int m_iBlockLimit;
};

#endif // !defined(AFX_XSOCKET_H__F9D1BA42_7338_11D2_A8E6_00 001C7030A6__INCLUDED_)


MOG

daeken_bb
12-19-2004, 02:36 PM
I like the base concept of it, and I like the structure, but the implementation isn't great (not to mention windows-only, but you already pointed that out hehe)

I was actually considering porting the network classes from Helios (the FreakU side-project) and using them. They essentially abstract everything... they can be replaced as neccesary so that we can have different network classes without issues (not just for different protocols, but for different OS's and such without ifdef ugliness)

Either way, thanks for the contribution. I'll most likely use quite a bit of it when writing the Windows network classes, even if we don't use your code directly :)

daeken_bb
12-19-2004, 02:38 PM
Btw... would you be able to break down the functions in the class? Some of them aren't too self-explanatory :)

MOG
12-19-2004, 03:32 PM
Hi,

It's 1:30AM and it's been a long time since I wrote that, mostly using as reference the book "Developer's Guide to Multiplayer Games". But I added comments now and that should help. If there is anything more let me know what specific functions or anything...

Is there a link to this Helios project you mentioned?

Another great cross-platform network library is HawkNL. Only problem with it is that it requires some sort of implementation in both client AND server.

zzz good night

MOG

daeken_bb
12-19-2004, 03:35 PM
Hi,

It's 1:30AM and it's been a long time since I wrote that, mostly using as reference the book "Developer's Guide to Multiplayer Games". But I added comments now and that should help. If there is anything more let me know what specific functions or anything...

Is there a link to this Helios project you mentioned?

Another great cross-platform network library is HawkNL. Only problem with it is that it requires some sort of implementation in both client AND server.

zzz good night

MOG

Ah, ok, thanks :)
I'll take a look tomorrow.

The Helios project was what FreakU grew into first... there was FreakU/Helios which was our own MMORPG when we decided not to use EQ's content, then there was FreakU/OpenEQ when we decided we would use it. FreakU/Helios still exists, but it's not the primary focus.

I'd rather write our own networking libraries as it'd save us time and allow us to tweak it more.