I have now done some changes and it have not crashed yet. The complete source code comes down but I only wonder one thing, is a good way to build multi server programs? Because I have no idea and have never done none network program before more than just copy and paste code. Thanks in advance.
#include <sstream>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <SFML/Network.hpp>
#include <SFML/System.hpp>
template <typename From, typename To>
To convert(const From & from)
{
std::stringstream stream;
stream << from;
To to;
stream >> to;
return to;
}
class ServerError
{
public:
std::string what;
ServerError(const std::string & er)
: what(er)
{
}
};
class Client : public sf::Thread
{
private:
sf::SocketTCP* socket;
sf::IPAddress* address;
sf::Int8 state;
public:
Client(sf::SocketTCP* m, sf::IPAddress*);
~Client();
virtual void Run();
static unsigned int getTotal();
sf::Int8 getState() const { return state; }
};
Client::Client(sf::SocketTCP* s, sf::IPAddress* a)
: socket(s), address(a), state(2)
{
}
Client::~Client()
{
delete socket;
delete address;
}
void Client::Run()
{
state = 1;
socket->Close();
state = 0;
}
class Server
{
private:
sf::Thread* gc_func;
sf::SocketTCP* socket;
sf::Mutex mutex_threads;
sf::Mutex mutex_lastcontainer;
std::map<std::string,std::clock_t> lastconnections;
std::vector<Client*> thread_clients;
sf::Int16 port;
bool listen;
bool gc_continue;
float gc_sleep_time;
float tbnc;
public:
Server();
void Init();
void Cleanup();
void Run();
friend void Server_GC(void*);
};
Server::Server() /* the program easy crash then gc_sleep_time = 0 */
: port(4029), gc_sleep_time(0), gc_continue(false), tbnc(0), socket(0), gc_func(0), listen(false)
{
}
void Server::Init()
{
using namespace sf;
gc_continue = true;
listen = true;
gc_func = new Thread(&Server_GC,this);
socket = new SocketTCP();
}
void Server_GC(void* data)
{
using namespace std;
Server* server = static_cast<Server*>(data);
while(server->gc_continue)
{
server->mutex_threads.Lock();
std::size_t size = server->thread_clients.size();
for(std::size_t i = 0; i < size;i++)
{
if(server->thread_clients[i]->getState() == 0)
{
delete server->thread_clients[i];
server->thread_clients.erase(server->thread_clients.begin()+i);
}
}
server->mutex_threads.Unlock();
server->mutex_lastcontainer.Lock();
for(map<string,clock_t>::iterator it = server->lastconnections.begin(); it != server->lastconnections.end(); it++)
{
if((*it).second < clock())
{
server->lastconnections.erase(it);
}
}
server->mutex_lastcontainer.Unlock();
sf::Sleep(server->gc_sleep_time);
}
}
void Server::Run()
{
using namespace sf;
using namespace std;
if(!socket->Listen(port))
{
throw ServerError("Could not start to listen at port " + convert<sf::Int16,std::string>(port));
}
gc_func->Launch();
while(listen)
{
SocketTCP* sock = new SocketTCP();
sf::IPAddress* address = new IPAddress();
if(socket->Accept(*sock, address) != Socket::Done)
{
delete sock;
delete address;
continue;
}
string ip = address->ToString();
mutex_lastcontainer.Lock();
if(lastconnections.end() != lastconnections.find(ip) && lastconnections[ip]*CLOCKS_PER_SEC > clock())
{
sock->Close();
delete sock;
delete address;
mutex_lastcontainer.Unlock();
continue;
}
lastconnections[ip] = clock()+CLOCKS_PER_SEC*tbnc;
mutex_lastcontainer.Unlock();
cout << "Client connected: " << address->ToString() << endl;
Lock mutex(mutex_threads);
thread_clients.push_back(new Client(sock,address));
thread_clients[thread_clients.size()-1]->Launch();
}
while(thread_clients.size() >= 0)
{
sf::Sleep(1);
}
gc_continue = false;
}
void Server::Cleanup()
{
gc_func->Wait();
delete gc_func;
}
int main(int argc, char args[])
{
using namespace std;
try
{
Server* server = new Server();
cout << "Init\n";
server->Init();
cout << "Running...\n";
server->Run();
cout << "Cleaning\n";
server->Cleanup();
cout << "Finish\n";
}
catch(...)
{
cerr << "Error..\n";
return 1;
}
return 0;
}
Besides, do anyone have any good link about Thread handling and network flow and stuff like it, please tell me then.