ServerSocket.h
#ifndef __SERVERSOCKET_H__
#define __SERVERSOCKET_H__

// #define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include "SocketManage.h"

#pragma warning(disable:4786)
using namespace std;


#define DEFAULT_PORT 6000
#define LISTEN_NUM 20
#define BUFFER_SIZE 32
#define CLIENT_IP 50


/**//// class CServerSocket forward declaration
class CServerSocket;


/**//// SInfo holds the data for thread parameter.
struct tagSInfo

...{
CServerSocket* pThis;
SOCKET ClientSocket;
char szMessage[BUFFER_SIZE];
char szClientIP[CLIENT_IP];
};

class CServerSocket

...{
public:
CServerSocket();
virtual ~CServerSocket();

/**//// Start Server
BOOL Start();

/**//// Stop Server
void Stop();

/**//// pure virtual function for future's inheritance.
virtual void OnMessage(LPSTR lpszIP, LPSTR lpszMessage) = 0;

/**//// Closing corresponding SOCKET's handle by its IP.
void CloseSocketByIP(LPCSTR lpszIP);

/**//// Send a message to client.
int SendMessageToClient(SOCKET hSocket, LPCSTR lpszMessage);
int SendMessageToClient(LPCSTR lpszIP, LPCSTR lpszMessage);

/**//// Send a message to all client.
void SendMessageToAllClient(LPCSTR lpszMessage);

/**//// Send a message to all client except for lpszIP
void SendMessageToAllClientExceptFor(LPCSTR lpszIP, LPCSTR lpszMessage);

/**//// recording SOCKET's status.
enum State

...{
SOCK_ERR,
SOCK_SUC
};

private:

/**//// Initialize SOCKET environment.
BOOL Initialization();

/**//// bind local with lPort
SOCKET Bind(USHORT lPort = DEFAULT_PORT);

/**//// accept a client's request and obtain its IP address by lpszIP.
SOCKET AcceptClient(SOCKET sListen, LPSTR lpszIP);

/**//// Worker Thraed that processing client's request.
static UINT __stdcall WorkThread(LPVOID pParam);
protected:
CSocketManage ClientManage;//! CSocketManage manages SOCKET and its IP address

private:
char szClientIP[50];
CRITICAL_SECTION cs;//! Critical_Section
};

#endif
#include "ServerSocket.h"
#include <process.h>
#include <stdio.h>
// #include <WINSOCK2.H>

#pragma comment(lib, "WS2_32")


/**//// Constructor
CServerSocket::CServerSocket()

...{

/**//// Initialize Critical Section
InitializeCriticalSection(&cs);
}


/**//// Destructor
CServerSocket:: ~CServerSocket()

...{

/**//// Delete Critical Section
DeleteCriticalSection(&cs);

/**//// Cleanup
Stop();
}


/**//// Initialize SOCKET environment.
BOOL CServerSocket::Initialization()

...{
WSADATA wsd;

/**//// Startup SOCKET library
if( WSAStartup(MAKEWORD(2, 2), &wsd) != 0) //! if failed, return FALSE

...{
return FALSE;
}

return TRUE;
}


/**//// Startup server
BOOL CServerSocket::Start()

...{

/**//// Initialize environment.
if (Initialization() == FALSE)

...{
return FALSE;
}


/**//// bind
SOCKET sockListen;
if ((sockListen = Bind(DEFAULT_PORT)) == NULL)

...{
return FALSE;
}


/**//// listen to client's request
while (TRUE)

...{
SOCKET sockClient = NULL;
while(sockClient == NULL)

...{
sockClient = AcceptClient(sockListen, szClientIP);
}


/**//// Insert Client's SOCKET and its IP address to ClientManage.
ClientManage.AddIPToSocket(sockClient, szClientIP);


/**//// alloc a memory for struct SInfo in heap, release it in WorkThread()
struct tagSInfo *SOCKINFO = new struct tagSInfo;

SOCKINFO->pThis = this;
SOCKINFO->ClientSocket = sockClient;
strcpy(SOCKINFO->szClientIP, szClientIP);
memset(SOCKINFO->szMessage, 0, BUFFER_SIZE);


/**//// Startup a thread , use SOCKINFO as its parameter.
_beginthreadex(NULL, 0, WorkThread, (LPVOID)SOCKINFO, 0, NULL);
}

return TRUE;
}


/**//// Startup a thread , use the SOCKINFO as its parameter.
UINT CServerSocket::WorkThread(LPVOID pParam)

...{
struct tagSInfo Param;

/**//// obtaining SOCKINFO
struct tagSInfo *lpParam = (struct tagSInfo*)pParam;

Param.ClientSocket = lpParam->ClientSocket;
Param.pThis = lpParam->pThis;
strcpy(Param.szClientIP, lpParam->szClientIP);
strcpy(Param.szMessage, lpParam->szMessage);

delete lpParam; //! release memory allocating in heap.
char recvbuf[BUFFER_SIZE];
State valState;


/**//// Receiving message from client and pass it to virtual function OnMessage()
while (TRUE)

...{
int nLeftToRecv = BUFFER_SIZE;
*recvbuf = 0;

/**//// do...while loop receives message until received it completely.
do

...{
char *pLeftBuf = (char *)( recvbuf + (BUFFER_SIZE - nLeftToRecv) );
int nRecvBytes = recv(Param.ClientSocket, pLeftBuf, nLeftToRecv, 0);
if(nRecvBytes == SOCKET_ERROR)

...{
valState = SOCK_ERR;
break;
}
nLeftToRecv -= nRecvBytes;
} while(nLeftToRecv > 0);

/**//// if has no errors in receiving progress, pass message to OnMessage().
if (valState != SOCK_ERR)

...{
Param.pThis->OnMessage(Param.szClientIP, recvbuf);
}
}

return 1;
}


/**//// bind local with lPort
SOCKET CServerSocket::Bind(USHORT lPort)

...{

/**//// creating a socket in tcp/ip protocol.
SOCKET sServer = socket(AF_INET, SOCK_STREAM, 0);

/**//// initializing socket struct.
struct sockaddr_in servAddr;
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(lPort);
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);


/**//// call socket api to bind
if(bind(sServer, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0)

...{
return NULL;
}

/**//// set SOCKET sServer to listening mode,and listen LISTEN_NUM at one time.
if(listen(sServer, LISTEN_NUM) != 0)

...{
return NULL;
}

return sServer;
}


/**//// accept a client's request and obtain its IP address by lpszIP.
SOCKET CServerSocket::AcceptClient(SOCKET sListen, LPSTR lpszIP)

...{
struct sockaddr_in cliAddrTmp;

int cliAddrSize = sizeof(struct sockaddr_in);
SOCKET sClient = accept(sListen, (struct sockaddr *)&cliAddrTmp, &cliAddrSize);

if(sClient == INVALID_SOCKET)

...{
return NULL;
}

EnterCriticalSection(&cs);

sprintf(lpszIP, "%s", inet_ntoa(cliAddrTmp.sin_addr));

LeaveCriticalSection(&cs);
return sClient;
}


/**//// Stop Server
void CServerSocket::Stop()

...{
ClientManage.CloseAllSocket();
WSACleanup();
}


/**//// close a socket by ip address.
void CServerSocket::CloseSocketByIP(LPCSTR lpszIP)

...{
if (lpszIP == NULL)

...{
return;
}

SOCKET sSocket = ClientManage.GetSocketByIP(lpszIP);
if (sSocket != NULL)

...{
closesocket(sSocket);
ClientManage.DeleteIPSocket(lpszIP);
}
}


/**//// Send a message to client.
int CServerSocket::SendMessageToClient(SOCKET hSocket, LPCSTR lpszMessage)

...{
int iResult = send(hSocket, lpszMessage, BUFFER_SIZE, 0);

return iResult;
}


/**//// Send a message to client.
int CServerSocket::SendMessageToClient(LPCSTR lpszIP, LPCSTR lpszMessage)

...{
int iResult;

SOCKET hSocket = ClientManage.GetSocketByIP(lpszIP);

iResult = send(hSocket, lpszMessage, BUFFER_SIZE, 0);

return iResult;
}


/**//// Send a message to all client.
void CServerSocket::SendMessageToAllClient(LPCSTR lpszMessage)

...{
std::list<std::string> lstIP;
std::list<std::string>::iterator iter;

ClientManage.GetAllClientIP(lstIP);
for (iter = lstIP.begin(); iter != lstIP.end(); ++iter)

...{
string IP = *iter;
SOCKET hSocket = ClientManage.GetSocketByIP(IP.c_str());
send(hSocket, lpszMessage, strlen(lpszMessage), 0);
}
}


/**//// Send a message to all client except for lpszIP
void CServerSocket::SendMessageToAllClientExceptFor(LPCSTR lpszIP, LPCSTR lpszMessage)

...{
std::list<std::string> lstIP;
std::list<std::string>::iterator iter;
ClientManage.GetAllClientIP(lstIP);
for (iter = lstIP.begin(); iter != lstIP.end(); ++iter)

...{
string IP = *iter;

/**//// except for lpszIP
if (strcmp(IP.c_str(), lpszIP) == 0)

...{
continue;
}

SOCKET hSocket = ClientManage.GetSocketByIP(IP.c_str());
send(hSocket, lpszMessage, strlen(lpszMessage), 0);
}
}
#ifndef __SOCKETMANAGE_H__
#define __SOCKETMANAGE_H__

#pragma warning(disable:4786)
#pragma warning(disable:4503)
#include <vector>
#include <list>
#include <map>
#include <string>
#include <algorithm>

class CSocketManage

...{
public:

/**//// Constructor
CSocketManage();

/**//// Destructor
virtual ~CSocketManage();


/**//// return all client's IP address by list<>
void GetAllClientIP(std::list<std::string> & list);


/**//// return client's number
LONG GetSocketCount() const;


/**//// insert a client to CSocketManage
void AddIPToSocket(SOCKET hSocket, LPCSTR lpszIP);


/**//// remove a client from CSocketManage
void DeleteIPSocket(LPCSTR lpszIP);


/**//// get socket by ip address
SOCKET GetSocketByIP(LPCSTR lpszIP);


/**//// close all socket connection.
void CloseAllSocket();
private:
std::map< std::string, std::vector<std::string> > m_mapClientToMessage;

std::map< std::string,SOCKET > m_mapIPToSocket;
};

#endif //__SOCKETMANAGE_H__
#include "stdafx.h"
#include "SocketManage.h"
#include <assert.h>

CSocketManage::CSocketManage()

...{
m_mapIPToSocket.clear();
}

CSocketManage:: ~CSocketManage()

...{

}

void CSocketManage::GetAllClientIP(std::list<std::string> & listIP)

...{

/**//// iterator's statement
std::map< std::string,SOCKET >::iterator iter;

for (iter = m_mapIPToSocket.begin();iter != m_mapIPToSocket.end();++iter)

...{
listIP.push_back(iter->first);
}
}

LONG CSocketManage::GetSocketCount() const

...{
return m_mapIPToSocket.size();
}

void CSocketManage::AddIPToSocket(SOCKET hSocket, LPCSTR lpszIP)

...{
m_mapIPToSocket.insert(std::make_pair(lpszIP, hSocket));
CString str;
str.Format("%d",m_mapIPToSocket.size());
AfxMessageBox(str);
}

void CSocketManage::DeleteIPSocket(LPCSTR lpszIP)

...{
std::map< std::string,SOCKET >::iterator iter;

for (iter = m_mapIPToSocket.begin();iter != m_mapIPToSocket.end();++iter)

...{

/**//// if found out target IP,then break
if(strcmp(iter->first.c_str(), lpszIP) == 0)

...{
break;
}
}


/**//// remove it from CSocketManage
m_mapIPToSocket.erase(iter);
}

SOCKET CSocketManage::GetSocketByIP(LPCSTR lpszIP)

...{
if (lpszIP == NULL)

...{
return NULL;
}

std::map< std::string,SOCKET >::iterator iter;

for (iter = m_mapIPToSocket.begin();iter != m_mapIPToSocket.end();++iter)

...{
if(strcmp(iter->first.c_str(), lpszIP) == 0)

...{
break;
}
}

return iter->second;
}


/**//// close all client's socket.
void CSocketManage::CloseAllSocket()

...{
std::map< std::string,SOCKET >::iterator iter;
for (iter = m_mapIPToSocket.begin();iter != m_mapIPToSocket.end();++iter)

...{
closesocket(iter->second);
}
}































































































ServerSocket.cpp
































































































































































































































































































































SocketManage.h





















































SocketManage.cpp







































































































