|
Server Socket Wrapper
Submitted by |
This is a socket wrapper that me and a friend wrote for use in a
MUD. For our senior year in High School we have to complete a project
that shows what we learned there, well a MUD shows SOME of what we
learned there(we all know you can't learn anything new about computers
in High School :p). The MUD is going to be sci-fi and we are working on
the design doc. Anyway, the MUD was being developed in windows and the
production machine is running FreeBSD 4.5. We needed a socket wrapper to
allow us to debug the MUD in Windows(gotta love VC++) and would work the
same(hopefully) in BSD without changing code. We also went the extra
mile to ensure that it worked with other BSD OS' as well. So far the
socket wrapper compiles 100% fine in the following OS': Windows 9x/NT 4
& 5/XP and FreeBSD 4.3 & 4.5. I hope someone may be able to find a use
for thise code.
A little about the authors, we both attend New Century Technology
High School in Alabama and are in the Computer Science strand.
Ben Everett works for C3 Interactive developing 3D plugins and
anything else they want him to do.
Chris Horlick gets to sit on his ass all day at the community pool,
collect money, and tell kids not to run(with the occasional coding
spree).
Currently the wrapper does NOT support address banning or binary
transfer, but it shouldn't be too much of a pain to add in support for
these very quickly.
Obike
|
Currently browsing [SocketWrapper.zip] (13,279 bytes) - [Socket Wrapper/Includes/BSDSocket.h] - (813 bytes)
#ifndef __BSD_SOCKET_H_
#define __BSD_SOCKET_H_
namespace CPPMUD
{
#ifndef _WIN32
// *NIX
class CBSDSocket : public CServerSocket
{
public:
// Constructor & Deconstructor
CBSDSocket();
virtual ~CBSDSocket();
// Public Accessor Functions
// Public Functions
virtual ErrRet CloseClient(int nClientID);
virtual ErrRet CloseSockets();
virtual ErrRet Connect(int nPort);
virtual ErrRet InitSockets();
virtual ErrRet Listen(int nPort);
virtual ErrRet ReadData(char *czData, int nBufferSize, int nClientID);
virtual void NonBlocking(SOCKET sSocket);
// Public Variables
protected:
// Protected Functions
virtual ErrRet CloseSocket(SOCKET sSocket);
virtual ErrRet SendData(int nClientID);
// Protected Variables
};
#endif
};
#endif |
|
Currently browsing [SocketWrapper.zip] (13,279 bytes) - [Socket Wrapper/Includes/ENGCore.h] - (552 bytes)
#ifndef __ENG_CORE_H_
#define __ENG_CORE_H_
namespace CPPMUD
{
#ifdef _WIN32
// Windows
#if _MSC_VER > 1000
#pragma once
#endif
#else
// *NIX
#endif
class CENGCore
{
public:
// Constructor & Deconstructor
CENGCore();
virtual ~CENGCore();
// Public Accessor Functions
void Quit() { m_bQuit = true; }
// Public Functions
void EngineLoop();
// Public Variables
protected:
// Protected Functions
// Protected Variables
bool m_bQuit;
CServerSocket *m_pSocket;
};
};
#endif |
|
Currently browsing [SocketWrapper.zip] (13,279 bytes) - [Socket Wrapper/Includes/Enums.h] - (591 bytes)
#ifndef __ENUMS_H_
#define __ENUMS_H_
namespace CPPMUD
{
#ifdef _WIN32
// Windows
#if _MSC_VER > 1000
#pragma once
#endif
#else
// *NIX
#endif
enum ConnState
{
csConnected,
csConnecting,
csDisconnecting,
csException,
csOverflow,
csTimeOut
};
enum ErrRet
{
errNone = 0,
errClientFullBuffer,
errSocketException,
errSocketFailClientConn,
errSocketFailCreate,
errSocketFailListen,
errSocketFailRead,
errSocketFailSelect,
errSocketFailWrite,
errSocketTimeOut,
errUnknownClient
};
};
#endif |
|
Currently browsing [SocketWrapper.zip] (13,279 bytes) - [Socket Wrapper/Includes/pch.h] - (300 bytes)
#ifndef __PCH_H_
#define __PCH_H_
#ifdef _WIN32
// Windows
#if _MSC_VER > 1000
#pragma once
#endif
#else
// *NIX
typedef unsigned int SOCKET;
#endif
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Enums.h"
#endif
|
|
Currently browsing [SocketWrapper.zip] (13,279 bytes) - [Socket Wrapper/Includes/Socket.h] - (2,593 bytes)
#ifndef __SOCKET_H_
#define __SOCKET_H_
namespace CPPMUD
{
#ifdef _WIN32
// Windows
#if _MSC_VER > 1000
#pragma once
#endif
#include <winsock2.h>
#else
// *NIX
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <netdb.h>
#endif
class CClientDescriptor
{
friend class CBSDSocket;
friend class CServerSocket;
friend class CWinSocket;
public:
// Constructor & Deconstructor
CClientDescriptor();
~CClientDescriptor();
// Public Accessor Functions
const bool IsInputPending() { return m_bInputPending; }
const char *GetInputBuffer() { return m_czIncomingData; }
const ConnState GetConnState() { return m_csState; }
const int GetClientID() { return m_nClientID; }
const int GetLineFromInputBuffer(char *czOutput, int nMaxLength);
const SOCKET GetSocket() { return m_sSocket; }
const void SetConnState(ConnState csState) { m_csState = csState; }
// Public Functions
// Public Variables
protected:
// Protected Functions
// Protected Variables
bool m_bInputPending;
char m_czIncomingData[2048];
char m_czOutgoingData[2048];
ConnState m_csState;
int m_nClientID;
sockaddr_in m_saClientInf;
SOCKET m_sSocket;
};
class CServerSocket
{
public:
// Constructor & Deconstructor
CServerSocket();
virtual ~CServerSocket();
// Public Accessor Functions
const int GetMaxClients() { return m_nMaxClients; }
const int GetNumClients() { return m_vecClients.size(); }
void SetMaxClients(int nMaxClients) { m_nMaxClients = nMaxClients; }
// Public Functions
ErrRet CheckForNewData();
ErrRet SendData(char *czData, int nBufferSize, int nClientID);
virtual ErrRet CloseClient(int nClientID) = 0;
virtual ErrRet CloseSockets() = 0;
virtual ErrRet Connect(int nPort) = 0;
virtual ErrRet InitSockets() = 0;
virtual ErrRet Listen(int nPort) = 0;
virtual ErrRet ReadData(char *czData, int nBufferSize, int nClientID) = 0;
virtual void NonBlocking(SOCKET sSocket) = 0;
// Public Variables
std::vector<CClientDescriptor> m_vecClients;
protected:
// Protected Functions
ErrRet NewClient();
int GetIndexFromClientID(int nClientID);
virtual ErrRet CloseSocket(SOCKET sSocket) = 0;
virtual ErrRet SendData(int nClientID) = 0;
// Protected Variables
int m_nMaxClients;
int m_nNextClientID;
sockaddr_in m_saAddress;
SOCKET m_sSocket;
};
};
#endif
|
|
Currently browsing [SocketWrapper.zip] (13,279 bytes) - [Socket Wrapper/Includes/WinSocket.h] - (883 bytes)
#ifndef __WIN_SOCKET_H_
#define __WIN_SOCKET_H_
namespace CPPMUD
{
#ifdef _WIN32
// Windows
#if _MSC_VER > 1000
#pragma once
#endif
class CWinSocket : public CServerSocket
{
public:
// Constructor & Deconstructor
CWinSocket();
virtual ~CWinSocket();
// Public Accessor Functions
// Public Functions
virtual ErrRet CloseClient(int nClientID);
virtual ErrRet CloseSockets();
virtual ErrRet Connect(int nPort);
virtual ErrRet InitSockets();
virtual ErrRet Listen(int nPort);
virtual ErrRet ReadData(char *czData, int nBufferSize, int nClientID);
virtual void NonBlocking(SOCKET sSocket);
// Public Variables
protected:
// Protected Functions
virtual ErrRet CloseSocket(SOCKET sSocket);
virtual ErrRet SendData(int nClientID);
// Protected Variables
WSADATA m_wsaData;
};
#endif
};
#endif |
|
Currently browsing [SocketWrapper.zip] (13,279 bytes) - [Socket Wrapper/Source/BSDSocket.cpp] - (5,518 bytes)
/*
BSDSocket.cpp
This file serves as the wrapper for all sockets in *NIX.
Copyright© 2002 Ben Everett and Chris Horlick.
All Rights Reserved.
*/
#include "pch.h"
#ifndef _WIN32
// *NIX
// Engine Includes
#include "Socket.h"
#include "BSDSocket.h"
using namespace CPPMUD;
// Constructor & Deconstructor
CBSDSocket::CBSDSocket()
{
}
CBSDSocket::~CBSDSocket()
{
}
// Functions
ErrRet CBSDSocket::CloseClient(int nClientID)
/*
Closes a client's connection by their client descriptor.
PRE: Server has been initialized properly, pClient is a valid pointer to a client descriptor.
POST: Client's connection closed.
*/
{
std::vector<CClientDescriptor>::iterator itRem = m_vecClients.begin();
// Remove the client from the client list.
for (int i = 0; i < m_vecClients.size(); ++i, ++itRem)
{
if (nClientID == m_vecClients[i].m_nClientID)
{
std::cout << "Closing client #" << m_vecClients[i].m_nClientID << "'s connection." <<
std::endl;
// Close the socket.
close(m_vecClients[i].m_sSocket);
m_vecClients.erase(itRem);
}
}
return errNone;
}
ErrRet CBSDSocket::CloseSocket(SOCKET sSocket)
/*
Closes a client's connection by their socket descriptor.
PRE: Server has been initialized properly, sSocket is a valid socket descriptor.
POST: Client's connection closed.
*/
{
std::cout << "Closing socket, connection timed out." << std::endl;
// Close the socket.
close(sSocket);
return errNone;
}
ErrRet CBSDSocket::CloseSockets()
/*
Closes all client sockets and finally the server socket.
PRE: Server was initialized properly.
POST: All sockets closed properly.
*/
{
// Close all client's connections.
for (int i = 0; i < m_vecClients.size(); ++i)
close(m_vecClients[i].m_sSocket);
// Close the server socket so no-one else can connect.
close(m_sSocket);
// Clear the client list.
m_vecClients.clear();
return errNone;
}
ErrRet CBSDSocket::Connect(int nPort)
/*
Connects to a server on the given port.
PRE: Server socket has been initialized properly, nPort is a valid port.
POST: Server is connected to a remote server.
*/
{
// For future use, to allow servers to be inter-connected.
return errNone;
}
ErrRet CBSDSocket::InitSockets()
/*
Initializes the server socket.
PRE: None.
POST: Server socket initialized.
*/
{
int nReuseAddr = 1;
// Obtain the server socket.
m_sSocket = socket(AF_INET, SOCK_STREAM, 0);
if (m_sSocket < 0)
return errSocketFailCreate;
// Setup non-blocking on the socket
NonBlocking(m_sSocket);
return errNone;
}
ErrRet CBSDSocket::Listen(int nPort)
/*
Listens for client connections on the given port.
PRE: Server has been initialized properly, nPort is a valid port.
POST: Server is listening for incoming client connections.
*/
{
m_saAddress.sin_family = AF_INET;
m_saAddress.sin_addr.s_addr = htonl(INADDR_ANY);
m_saAddress.sin_port = htons(nPort);
// Bind the socket.
if (bind(m_sSocket, (sockaddr*)&m_saAddress, sizeof(m_saAddress)) < 0)
{
close(m_sSocket);
return errSocketFailCreate;
}
// Listen for any incoming connections.
if (listen(m_sSocket, 10) != 0)
{
close(m_sSocket);
return errSocketFailListen;
}
return errNone;
}
ErrRet CBSDSocket::ReadData(char *czData, int nBufferSize, int nClientID)
/*
Reads data from the client descriptor and copies it into czData.
PRE: Server has been initialized properly, czData is a valid pointer to the read buffer,
pClient is a valid pointer to a client descriptor, nBufferSize is the length of czData..
POST: Client data has been read.
*/
{
int nIndex = GetIndexFromClientID(nClientID);
int nRead = 0;
if (nIndex < 0)
return errUnknownClient;
nRead = recv(m_vecClients[nIndex].m_sSocket, czData, nBufferSize, 0);
if (nRead < 0)
return errSocketTimeOut;
else if (nRead == 0)
return errSocketFailRead;
return errNone;
}
ErrRet CWinSocket::SendData(int nClientID)
/*
Sends as much data as possible in nClientID's outgoing buffer.
PRE: Server has been initialized properly, nClientID is a valid client ID.
POST: As much data as possible is sent from the client's outgoing buffer.
*/
{
int nIndex = GetIndexFromClientID(nClientID);
int nLen = strlen(m_vecClients[nIndex].m_czOutgoingData);
int nSent = 0;
// Send as much data as possible to the client.
nSent = write(m_vecClients[nIndex].m_sSocket, m_vecClients[nIndex].m_czOutgoingData,
strlen(m_vecClients[nIndex].m_czOutgoingData), 0);
// If nSent is < 0 the socket timed out, if it = 0 there was an error somewhere, if > 0 nSent
// removes that many char's from the outgoing buffer.
if (nSent < 0)
return errSocketTimeOut;
else if (nSent == 0)
return errSocketFailWrite;
else
{
memmove(m_vecClients[nIndex].m_czOutgoingData, m_vecClients[nIndex].m_czOutgoingData +
nSent, 2048 - nSent);
memset(m_vecClients[nIndex].m_czOutgoingData + (nLen - nSent), 0, sizeof(char) *
(nLen - nSent));
}
return errNone;
}
void CBSDSocket::NonBlocking(SOCKET sSocket)
/*
Sets the given socket to non-blocking mode.
PRE: Server has been initialized properly, sSocket is a valid socket descriptor.
POST: Socket set to non-blocking mode.
*/
{
int nOptions = fcntl(sSocket, F_GETFL);
if (nOptions < 0)
return;
nOptions |= O_NONBLOCK;
if (fcntl(sSocket, F_SETFL, nOptions) < 0)
return;
}
#endif
|
|
Currently browsing [SocketWrapper.zip] (13,279 bytes) - [Socket Wrapper/Source/ENGCore.cpp] - (2,035 bytes)
/*
ENGCore.cpp
This file serves as the core for the engine, performing the engine loop.
Copyright© 2002 Ben Everett and Chris Horlick.
All Rights Reserved.
*/
#include "pch.h"
// Engine Includes
#include "Socket.h"
#include "BSDSocket.h"
#include "WinSocket.h"
#include "ENGCore.h"
using namespace CPPMUD;
// Constructor & Deconstructor
CENGCore::CENGCore()
{
m_bQuit = false;
m_pSocket = NULL;
}
CENGCore::~CENGCore()
{
if (m_pSocket)
delete m_pSocket;
m_pSocket = NULL;
}
// Functions
void CENGCore::EngineLoop()
{
char czMessage[] = "You alive?\r\n";
#ifdef _WIN32
m_pSocket = new CWinSocket;
#else
m_pSocket = new CBSDSocket;
#endif
if (!m_pSocket)
return;
// Unable to initialize sockets.
if (m_pSocket->InitSockets() != errNone)
{
if (m_pSocket)
delete m_pSocket;
m_pSocket = NULL;
return;
}
// Unable to listen on port 8000.
if (m_pSocket->Listen(8000) != errNone)
{
if (m_pSocket)
delete m_pSocket;
m_pSocket = NULL;
return;
}
// Engine loop.
while (!m_bQuit)
{
char czCommand[1024] = "";
memset(czCommand, 0, sizeof(char) * 1024);
if (m_pSocket->CheckForNewData() != errNone)
break;
for (int i = 0; i < m_pSocket->m_vecClients.size(); ++i)
{
int nLen = 0;
if (m_pSocket->m_vecClients[i].IsInputPending())
{
nLen = m_pSocket->m_vecClients[i].GetLineFromInputBuffer(czCommand, 1024);
m_pSocket->SendData(czCommand, nLen, m_pSocket->m_vecClients[i].GetClientID());
memset(czCommand, 0, sizeof(char) * 1024);
}
}
// Sleep for 100 milliseconds, to simulate ~10FPS... don't want to take up the entire CPU.
// *NOTE* Change this for your purposes, we just threw this in here for this wrapper
// example. Our architecture is different from this examples. :)
Sleep(100);
}
// Close all sockets.
m_pSocket->CloseSockets();
// De-allocate the socket.
if (m_pSocket)
delete m_pSocket;
m_pSocket = NULL;
} |
|
Currently browsing [SocketWrapper.zip] (13,279 bytes) - [Socket Wrapper/Source/Main.cpp] - (804 bytes)
/*
Main.cpp
This file serves as the main entry point for the MUD.
Copyright© 2002 Ben Everett and Chris Horlick.
All Rights Reserved.
*/
#include "pch.h"
// Engine Includes
#include "Socket.h"
#include "BSDSocket.h"
#include "WinSocket.h"
#include "ENGCore.h"
using namespace std;
// Functions
int main(int argc, char *argv[])
{
CPPMUD::CENGCore *pCore = NULL;
cout << "C++ MUD Base Code v0.1" << endl;
cout << "Allocating engine... ";
pCore = new CPPMUD::CENGCore;
if (!pCore)
{
cout << "failed." << endl;
return -1;
}
cout << "done." << endl << endl << "Entering game loop..." << endl << endl;
pCore->EngineLoop();
cout << endl << "Game loop complete, exiting." << endl;
if (pCore)
delete pCore;
pCore = NULL;
return 0;
} |
|
Currently browsing [SocketWrapper.zip] (13,279 bytes) - [Socket Wrapper/Source/pch.cpp] - (16 bytes)
|
Currently browsing [SocketWrapper.zip] (13,279 bytes) - [Socket Wrapper/Source/Socket.cpp] - (7,033 bytes)
/*
Socket.cpp
This file serves as the base for all sockets.
Copyright© 2002 Ben Everett and Chris Horlick.
All Rights Reserved.
*/
#include "pch.h"
// Engine Includes
#include "Socket.h"
using namespace CPPMUD;
// Constructor & Deconstructor
CClientDescriptor::CClientDescriptor()
{
}
CClientDescriptor::~CClientDescriptor()
{
}
CServerSocket::CServerSocket()
{
m_nMaxClients = 1;
m_nNextClientID = 0;
m_vecClients.clear();
}
CServerSocket::~CServerSocket()
{
}
// Functions
const int CClientDescriptor::GetLineFromInputBuffer(char *czOutput, int nMaxLength)
/*
Obtains an entire line from the incoming data buffer.
PRE: Server has been initialized properly, czOutput is a valid pointer to a character array,
nMaxLength is the amount of character's czOutput can hold.
POST: Line copied from incoming data buffer to czOutput and the length of the line returned.
*/
{
char *cLineEnd = strstr(m_czIncomingData, "\n");
int nLen = strlen(m_czIncomingData);
int nLineEnd = cLineEnd - m_czIncomingData + 1;
// Make sure we found an line in the input buffer.
if (cLineEnd == NULL)
return 0;
// Copy the line from the input buffer to czOutput.
for (int i = 0; i < nLineEnd; ++i)
{
// Make sure we haven't surpassed the length of czOutput.
if (i >= nMaxLength)
break;
czOutput[i] = m_czIncomingData[i];
}
// Remove the line from the incoming data buffer.
// *NOTE* In the MUD we truncate all data that surpasses czOutput, you may want to change this
// for your purposes.
memmove(m_czIncomingData, m_czIncomingData + nLineEnd, 2048 - nLineEnd);
memset(m_czIncomingData + (nLen - nLineEnd), 0, sizeof(char) * (nLen - nLineEnd));
return i;
}
ErrRet CServerSocket::CheckForNewData()
/*
Checks for pending client connection attempts and incoming/outgoing client data.
PRE: Server has been initialized properly.
POST: New clients connected and incoming/outgoing data flags have been set for each client.
*/
{
ErrRet retVal;
fd_set fdExcept, fdRead, fdWrite;
int i = 0;
SOCKET sMaxDesc;
timeval timeNone;
timeNone.tv_sec = timeNone.tv_usec = 0;
FD_ZERO(&fdExcept);
FD_ZERO(&fdRead);
FD_ZERO(&fdWrite);
FD_SET(m_sSocket, &fdExcept);
FD_SET(m_sSocket, &fdRead);
FD_SET(m_sSocket, &fdWrite);
sMaxDesc = m_sSocket;
for (i = 0; i < m_vecClients.size(); ++i)
{
FD_SET(m_vecClients[i].m_sSocket, &fdRead);
FD_SET(m_vecClients[i].m_sSocket, &fdWrite);
// Clear the incoming/outgoing data flags.
m_vecClients[i].m_bInputPending = false;
// Make sure we have the highest socket descriptor.
if (m_vecClients[i].m_sSocket > sMaxDesc)
sMaxDesc = m_vecClients[i].m_sSocket;
}
select(sMaxDesc + 1, &fdRead, &fdWrite, &fdExcept, &timeNone);
// Check to make sure the server socket hasn't had an exception.
if (FD_ISSET(m_sSocket, &fdExcept))
{
std::cout << "The server socket has encountered an exception, aborting..." << std::endl;
return errSocketException;
}
// Check for incoming connections.
if (FD_ISSET(m_sSocket, &fdRead))
{
retVal = NewClient();
if (retVal != errNone)
return retVal;
}
// Check all client sockets for incoming/outgoing data.
for (i = 0; i < m_vecClients.size(); ++i)
{
// Incoming data, set incoming data flag on client.
if (FD_ISSET(m_vecClients[i].m_sSocket, &fdRead))
{
m_vecClients[i].m_bInputPending = true;
retVal = ReadData(m_vecClients[i].m_czIncomingData, 2048, m_vecClients[i].m_nClientID);
if ((retVal != errNone) && (retVal == errSocketTimeOut))
{
CloseClient(m_vecClients[i].m_nClientID);
continue;
}
}
// Send as much outgoing data as possible to the client.
retVal = SendData(m_vecClients[i].m_nClientID);
if ((retVal != errNone) && (retVal == errSocketTimeOut))
{
CloseClient(m_vecClients[i].m_nClientID);
continue;
}
// Close the connection if the client is overflow and all data has been sent.
if (m_vecClients[i].m_csState == csOverflow)
{
if (strlen(m_vecClients[i].m_czOutgoingData) == 0)
{
CloseClient(m_vecClients[i].m_nClientID);
continue;
}
}
}
return errNone;
}
ErrRet CServerSocket::NewClient()
/*
Handles a client connection to the server.
PRE: Server has been initialized properly.
POST: Client connected to the server.
*/
{
CClientDescriptor cdClient;
char *czServerFull = "We are sorry for the inconvenience, but the server is currently full.\nPlease try again later.\n";
int nLen = sizeof(cdClient.m_saClientInf);
// Set the connection state and client ID.
cdClient.m_nClientID = m_nNextClientID++;
memset(cdClient.m_czIncomingData, 0, sizeof(char) * 2048);
memset(cdClient.m_czOutgoingData, 0, sizeof(char) * 2048);
// Accept the incoming connection.
// *NOTE* May want to make this a virtual function and let CBSDSocket and CWinSocket handle this.
#ifdef _WIN32
cdClient.m_sSocket = accept(m_sSocket, (sockaddr*)&cdClient.m_saClientInf, &nLen);
#else
cdClient.m_sSocket = accept(m_sSocket, (sockaddr*)&cdClient.m_saClientInf, (socklen_t*)&nLen);
#endif
// Server is full, close the connection.
if (m_vecClients.size() >= m_nMaxClients)
{
std::cout << "Server full, refusing access to incoming client #" << cdClient.m_nClientID <<
"." << std::endl;
cdClient.m_csState = csOverflow;
strcpy(cdClient.m_czOutgoingData, czServerFull);
}
else
{
// Set the connection state to connected.
cdClient.m_csState = csConnected;
std::cout << "Access to incoming connection permitted, new client #" << cdClient.m_nClientID <<
"." << std::endl;
strcpy(cdClient.m_czOutgoingData, "Connected.\r\n");
}
// Set the client socket to non-blocking.
NonBlocking(cdClient.m_sSocket);
// Append the client to the client list.
m_vecClients.push_back(cdClient);
return errNone;
}
ErrRet CServerSocket::SendData(char *czData, int nBufferSize, int nClientID)
/*
Appends data to a client's output buffer.
PRE: czData is a valid pointer to a character array, nBufferSize is the length of czData,
nClientID is whom the data is intended for.
POST: New clients connected and incoming/outgoing data flags have been set for each client.
*/
{
int nIndex = GetIndexFromClientID(nClientID);
int nOutputLen = strlen(m_vecClients[nIndex].m_czOutgoingData);
// Make sure there is room for the outgoing data.
if ((nBufferSize + nOutputLen) > 2048)
return errClientFullBuffer;
sprintf(m_vecClients[nIndex].m_czOutgoingData + nOutputLen, "%s", czData);
return errNone;
}
int CServerSocket::GetIndexFromClientID(int nClientID)
/*
Returns an index into the client vector.
PRE: None.
POST: A index is returned from the client ID.
*/
{
// Find the index from the client ID.
for (int i = 0; i < m_vecClients.size(); ++i)
{
if (m_vecClients[i].m_nClientID == nClientID)
return i;
}
return -1;
} |
|
Currently browsing [SocketWrapper.zip] (13,279 bytes) - [Socket Wrapper/Source/WinSocket.cpp] - (5,961 bytes)
/*
WinSocket.cpp
This file serves as the wrapper for all sockets in *NIX.
Copyright© 2002 Ben Everett and Chris Horlick.
All Rights Reserved.
*/
#include "pch.h"
#ifdef _WIN32
// Windows
// Engine Includes
#include "Socket.h"
#include "WinSocket.h"
using namespace CPPMUD;
// Constructor & Deconstructor
CWinSocket::CWinSocket()
{
}
CWinSocket::~CWinSocket()
{
}
// Functions
ErrRet CWinSocket::CloseClient(int nClientID)
/*
Closes a client's connection by their client descriptor.
PRE: Server has been initialized properly, pClient is a valid pointer to a client descriptor.
POST: Client's connection closed.
*/
{
std::vector<CClientDescriptor>::iterator itRem = m_vecClients.begin();
// Remove the client from the client list.
for (int i = 0; i < m_vecClients.size(); ++i, ++itRem)
{
if (nClientID == m_vecClients[i].m_nClientID)
{
std::cout << "Closing client #" << m_vecClients[i].m_nClientID << "'s connection." <<
std::endl;
// Close the socket.
shutdown(m_vecClients[i].m_sSocket, SD_BOTH);
closesocket(m_vecClients[i].m_sSocket);
m_vecClients.erase(itRem);
}
}
return errNone;
}
ErrRet CWinSocket::CloseSocket(SOCKET sSocket)
/*
Closes a client's connection by their socket descriptor.
PRE: Server has been initialized properly, sSocket is a valid socket descriptor.
POST: Client's connection closed.
*/
{
std::cout << "Closing socket, connection timed out." << std::endl;
// Close the socket.
shutdown(sSocket, SD_BOTH);
closesocket(sSocket);
return errNone;
}
ErrRet CWinSocket::CloseSockets()
/*
Closes all client sockets and finally the server socket.
PRE: Server was initialized properly.
POST: All sockets closed properly.
*/
{
// Close all client's connections.
for (int i = 0; i < m_vecClients.size(); ++i)
{
shutdown(m_vecClients[i].m_sSocket, SD_BOTH);
closesocket(m_vecClients[i].m_sSocket);
}
// Close the server socket so no-one else can connect.
shutdown(m_sSocket, SD_BOTH);
closesocket(m_sSocket);
// Clear the client list.
m_vecClients.clear();
return errNone;
}
ErrRet CWinSocket::Connect(int nPort)
/*
Connects to a server on the given port.
PRE: Server socket has been initialized properly, nPort is a valid port.
POST: Server is connected to a remote server.
*/
{
return errNone;
}
ErrRet CWinSocket::InitSockets()
/*
Initializes the server socket.
PRE: None.
POST: Server socket initialized.
*/
{
// Start WinSock.
if (WSAStartup(0x0202, &m_wsaData))
{
printf("Failed.\nFailed to initialize WinSock 2.\n");
return errSocketFailCreate;
}
// Make sure we are running WinSock v2.
if (m_wsaData.wVersion != 0x0202)
{
printf("Failed.\nInvalid version of WinSock.\n");
return errSocketFailCreate;
}
// Initialize the socket.
m_sSocket = socket(AF_INET, SOCK_STREAM, 0);
// Setup non-blocking on the socket.
NonBlocking(m_sSocket);
return errNone;
}
ErrRet CWinSocket::Listen(int nPort)
/*
Listens for client connections on the given port.
PRE: Server has been initialized properly, nPort is a valid port.
POST: Server is listening for incoming client connections.
*/
{
m_saAddress.sin_family = AF_INET;
m_saAddress.sin_port = htons(nPort);
m_saAddress.sin_addr.s_addr = htonl(INADDR_ANY);
// Bind the socket.
if (bind(m_sSocket, (LPSOCKADDR)&m_saAddress, sizeof(m_saAddress)) == SOCKET_ERROR)
{
printf("Failed.\nUnable to bind port.\n");
return errSocketFailCreate;
}
// Listen for any incoming connections.
if (listen(m_sSocket, 10) == SOCKET_ERROR)
{
printf("Failed.\nUnable to listen for incoming connections.\n");
return errSocketFailListen;
}
return errNone;
}
ErrRet CWinSocket::ReadData(char *czData, int nBufferSize, int nClientID)
/*
Reads data from the client descriptor and copies it into czData.
PRE: Server has been initialized properly, czData is a valid pointer to the read buffer,
pClient is a valid pointer to a client descriptor, nBufferSize is the length of czData..
POST: Client data has been read.
*/
{
int nIndex = GetIndexFromClientID(nClientID);
int nRead = 0;
if (nIndex < 0)
return errUnknownClient;
nRead = recv(m_vecClients[nIndex].m_sSocket, czData, nBufferSize, 0);
if (nRead < 0)
return errSocketTimeOut;
else if (nRead == 0)
return errSocketFailRead;
return errNone;
}
ErrRet CWinSocket::SendData(int nClientID)
/*
Sends as much data as possible in nClientID's outgoing buffer.
PRE: Server has been initialized properly, nClientID is a valid client ID.
POST: As much data as possible is sent from the client's outgoing buffer.
*/
{
int nIndex = GetIndexFromClientID(nClientID);
int nSent = 0;
int nLen = strlen(m_vecClients[nIndex].m_czOutgoingData);
// Send as much data as possible to the client.
nSent = send(m_vecClients[nIndex].m_sSocket, m_vecClients[nIndex].m_czOutgoingData,
strlen(m_vecClients[nIndex].m_czOutgoingData), 0);
// If nSent is < 0 the socket timed out, if it = 0 there was an error somewhere, if > 0 nSent
// removes that many char's from the outgoing buffer.
if (nSent < 0)
return errSocketTimeOut;
else if (nSent == 0)
return errSocketFailWrite;
else
{
memmove(m_vecClients[nIndex].m_czOutgoingData, m_vecClients[nIndex].m_czOutgoingData +
nSent, 2048 - nSent);
memset(m_vecClients[nIndex].m_czOutgoingData + (nLen - nSent), 0, sizeof(char) * (nLen -
nSent));
}
return errNone;
}
void CWinSocket::NonBlocking(SOCKET sSocket)
/*
Sets the given socket to non-blocking mode.
PRE: Server has been initialized properly, sSocket is a valid socket descriptor.
POST: Socket set to non-blocking mode.
*/
{
unsigned long lNonBlocking = 1;
// Set the socket to non-blocking.
ioctlsocket(sSocket, FIONBIO, &lNonBlocking);
}
#endif |
|
The zip file viewer built into the Developer Toolbox made use
of the zlib library, as well as the zlibdll source additions.
|