The ThreadSafeVector.h contains only a class which wraps the std::vector functions using boost mutexes to ensure thread safety. Won`t post that, if you can`t do this, use a regular std::vector instead. If you can`t use std::vector then get a new hobby.
PHP Code:
#ifndef SOCKETSYSTEM_H_
#define SOCKETSYSTEM_H_
#include <winsock2.h>
#include <iostream>
#include <boost/thread.hpp>
#include <cstring>
#include "ThreadSafeVector.h"
using namespace std;
typedef unsigned char byte;
class CServerSocket;
class CClientSocket
{
private:
CServerSocket* m_Server;
SOCKET m_Socket;
sockaddr_in m_Address;
byte* m_Buffer;
public:
CServerSocket* GetServer() { return this->m_Server; }
unsigned int GetConnection() { return this->m_Socket; }
sockaddr_in GetAddress() { return this->m_Address; }
byte* GetBuffer() { return this->m_Buffer; }
void* Wrapper;
int Send(void* Data, int Length);
int Disconnect();
CClientSocket(CServerSocket* Server, SOCKET Client, sockaddr_in Address, int BufferSize);
~CClientSocket(void);
};
class CServerSocket
{
private:
ThreadSafeVector<cclientsocket*>* Clients;
SOCKET m_ListenSocket;
int m_Port;
int m_Backlog;
int m_ClientBufferSize;
void AcceptFunction();
void ReceiveFunction();
boost::thread* AcceptThread;
boost::thread* ReceiveThread;
public:
void (*ClientConnected)(CClientSocket* Client, CServerSocket* Server);
void (*ClientDisconnected)(CClientSocket* Client, CServerSocket* Server);
void (*ClientError)(CClientSocket* Client, CServerSocket* Server, int Error);
void (*DataReceived)(CClientSocket* Client, CServerSocket* Server, byte* Data, int DataLength);
string ServerName;
CServerSocket(int Port, int Backlog, string Name);
~CServerSocket(void);
};
#endif
PHP Code:
#include "SocketSystem.hpp"
using namespace std;
// client
CClientSocket::CClientSocket(CServerSocket* Server, SOCKET Client, sockaddr_in Address, int BufferLength)
{
this->m_Server = Server;
this->m_Socket = Client;
this->m_Address = Address;
this->m_Buffer = new byte[BufferLength];
}
CClientSocket::~CClientSocket(void)
{
closesocket(this->m_Socket);
delete[] this->m_Buffer;
}
int CClientSocket::Send(void* Data, int Length)
{
int datasent = send(m_Socket, (const char*)Data, Length, 0);
if(datasent==SOCKET_ERROR)
return SOCKET_ERROR;
else if(datasent < Length)
return 1;
return 0;
}
int CClientSocket::Disconnect()
{
return closesocket(m_Socket);
}
// Server
void CServerSocket::AcceptFunction()
{
// constantly looping, accepting connections
// when a connection is received, add it to the client list
while(true)
{
sockaddr_in caddr;
int alen = sizeof(caddr);
SOCKET client = accept(m_ListenSocket, (sockaddr*)&caddr, &alen); // Alan, lol
if(client==INVALID_SOCKET)
{
continue;
}
CClientSocket * _Client = new CClientSocket(this, client, caddr, this->m_ClientBufferSize);
this->Clients->push_back(_Client);
if(this->ClientConnected!=NULL)
{
this->ClientConnected(_Client, this);
}
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
}
}
void CServerSocket::ReceiveFunction()
{
// Constantly loop through the client connection, receiving data
while(true)
{
CClientSocket* Client;
for(int i=0; i < this->Clients->size(); ++i)
{
Client = this->Clients->at(i);
fd_set fd; fd.fd_array[0] = Client->GetConnection(); fd.fd_count = 1; timeval tval; tval.tv_usec = 1000; tval.tv_sec = 0;
bool disconnect = false;
int error = select(0, &fd, NULL, NULL, &tval);
if(error>0)
{
int recvlen = recv(Client->GetConnection(), (char*)Client->GetBuffer(), this->m_ClientBufferSize, 0);
error = recvlen;
if(error==0) disconnect = true;
if(error!=SOCKET_ERROR)
{
byte* buffer = new byte[recvlen];
memcpy(buffer, Client->GetBuffer(), recvlen);
if(this->DataReceived != NULL)
{
this->DataReceived(Client, this, buffer, recvlen);
}
delete[] buffer;
}
}
if(error==SOCKET_ERROR)
{
disconnect = true;
if(this->ClientError != NULL)
{
this->ClientError(Client, this, WSAGetLastError());
}
}
if(disconnect)
{
if(this->ClientDisconnected != NULL)
{
this->ClientDisconnected(Client, this);
}
this->Clients->erase(i);
delete Client;
i--;
}
}
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
}
}
CServerSocket::~CServerSocket(void)
{
cout << '[' << ServerName << ']' << " Shutting down . . . " << endl;
// this->Clients->clear();
this->AcceptThread->interrupt();
this->ReceiveThread->interrupt();
closesocket(m_ListenSocket);
}
CServerSocket::CServerSocket(int Port, int Backlog, string Name)
{
this->Clients = new ThreadSafeVector<CClientSocket*>();
ServerName = Name;
m_Port = Port; m_Backlog = Backlog;
WSADATA wsaData; int Result;
m_ClientBufferSize = 4096;
Result = WSAStartup(MAKEWORD(2,2), &wsaData);
if(Result == NO_ERROR)
{
m_ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(m_ListenSocket!=INVALID_SOCKET)
{
sockaddr_in addr;
ZeroMemory((char*)&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(m_Port);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(m_ListenSocket, (sockaddr*)&addr, sizeof(addr)) != SOCKET_ERROR)
{
if(listen(m_ListenSocket, m_Backlog) != SOCKET_ERROR)
{
cout << '[' << ServerName << ']' << " Listening on port " << m_Port << endl;
this->AcceptThread = new boost::thread(boost::bind(&CServerSocket::AcceptFunction, this));
this->ReceiveThread = new boost::thread(boost::bind(&CServerSocket::ReceiveFunction, this));
}
else
{
cerr << "listen() error : " << WSAGetLastError() << endl;
}
}
else
{
closesocket(m_ListenSocket);
cerr << "bind() error : " << WSAGetLastError() << endl;
}
}
else
{
cerr << "socket() error : " << WSAGetLastError() << endl;
}
}
else
{
cerr << "WSAStartup() error!" << endl;
}
}