Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Multiserver, crash on many connections  (Read 8673 times)

0 Members and 1 Guest are viewing this topic.

hajacken

  • Newbie
  • *
  • Posts: 11
    • View Profile
Multiserver, crash on many connections
« on: February 20, 2009, 09:33:43 pm »
Hi everyone :)
I have just created my first multi server by using threads but I got one problem, it crash too easy. You simply only need to write this:
Code: [Select]

while(true)
{
        sf::SocketTCP socket;
        if (socket.Connect(4029, "127.0.0.1") != sf::Socket::Done)
        {
            continue;
        }
        sf::Packet packet;
        packet << "hello";
        socket.Send(packet);
        socket.Close();
}

and put it in a thread and then will the program crash with status -1073741819 after some time (randomly, often less than 3 sec). Do anyone have any clue what I can do to stop prevent it?

Tell me if I need to show my source code.

[edit]
It work perfectly if I set a sleep(0.1) in the while loop and it have none memory leaks or something like it so it not that which is the problem.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Multiserver, crash on many connections
« Reply #1 on: February 20, 2009, 09:39:21 pm »
Yeah, you should show us a minimal and complete example reproducing the problem. With both client and server code.
Laurent Gomila - SFML developer

hajacken

  • Newbie
  • *
  • Posts: 11
    • View Profile
Multiserver, crash on many connections
« Reply #2 on: February 20, 2009, 09:50:39 pm »
Code: [Select]

#include <iostream>
#include <string>
#include <vector>

#include <SFML/Network.hpp>
#include <SFML/System.hpp>

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();

    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()
{
    this->state = 1;
    sf::Packet packet;
    packet << "Hello";
    this->socket->Send(packet);
    packet.Clear();
    this->socket->Receive(packet);
    this->socket->Close();
    this->state = 0;
}

class Server
{
    private:
    sf::Thread* gc_func;

    unsigned int run_at_port;
    unsigned long long int max_clients;
    bool keep_listen;

    std::vector<Client*> thread_clients;

    sf::Mutex mutex_clients;
    bool gc_continue;
    float gc_sleep_time;
    public:
    Server();
    void Init();

    void Cleanup();
    void Run();
    void gc();

    friend void Server_GC(void*);
};

Server::Server()
{
    run_at_port = 4029;
    max_clients = 10;

    gc_sleep_time = 0;
    gc_continue = false;
}

void Server::Init()
{
    gc_func = 0;
    gc_func = new sf::Thread(&Server_GC,this);
    gc_continue = true;
    gc_func->Launch();
    keep_listen = true;
}

void Server_GC(void* data)
{
    Server* server = static_cast<Server*>(data);

    while(server->gc_continue)
    {
        std::size_t size = server->thread_clients.size();
        for(std::size_t i = 0; i < size;i++)
        {
            if(server->thread_clients.at(i)->getState() == 0)
            {
                server->mutex_clients.Lock();
                delete server->thread_clients.at(i);
                server->thread_clients.erase(server->thread_clients.begin()+i);
                server->mutex_clients.Unlock();
            }
        }
        sf::Sleep(server->gc_sleep_time);
    }
}
void Server::Run()
{
    using namespace sf;
    SocketTCP conn;
    if(!conn.Listen(this->run_at_port))
    {
        throw ServerError("mohaah");
    }
    while(keep_listen)
    {
        SocketTCP* sock = new SocketTCP();
        sf::IPAddress* address = new IPAddress();

        this->mutex_clients.Lock();
        thread_clients.push_back(new Client(sock,address));
        thread_clients[thread_clients.size()-1]->Launch();

        this->mutex_clients.Unlock();

        while(thread_clients.size() >= max_clients)
        {

        }
    }
    while(thread_clients.size() >= 0)
    {
            sf::Sleep(1);
    }
    conn.Close();
}
void Server::Cleanup()
{
    if(gc_func != 0)
    {
        gc_func->Terminate();
        delete gc_func;
    }
}

void Connecter(void* a)
{
    while(true)
    {
        std::cout << "Mohaha";
        sf::SocketTCP socket;
        if (socket.Connect(4029, "127.0.0.1") != sf::Socket::Done)
        {
            continue;
        }
        sf::Packet packet;
        packet << "hellow";
        socket.Send(packet);
        socket.Close();
        //break;
        sf::Sleep(0);
    }
}

int main(int argc, char args[])
{
    try
    {
        sf::Thread connecter(&Connecter);
        connecter.Launch();
        Server* server = new Server();
        server->Init();
        server->Run();
        server->Cleanup();
    }
    catch(ServerError & a)
    {
        std::cerr << a.what << std::endl;
        throw;
    }
    catch(std::exception & a)
    {
        std::cerr << a.what() << std::endl;
        throw;
    }
    catch(...)
    {
        return 1;
    }
    return 0;
}


I know the code is messy and I will fix it, but just now will I only get it too work.

hajacken

  • Newbie
  • *
  • Posts: 11
    • View Profile
Multiserver, crash on many connections
« Reply #3 on: February 21, 2009, 01:12:55 am »
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.

Code: [Select]

#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.

hajacken

  • Newbie
  • *
  • Posts: 11
    • View Profile
Multiserver, crash on many connections
« Reply #4 on: February 21, 2009, 01:32:54 am »
I got a new question, if I use sf::Sleep to wait in a thread, will it be CPU waste or will the CPU cycles just go to another thread?

Example:if I write a sleep function like this:
Code: [Select]

void sleep(float s)
{
  clock_t end;
  end = clock () + s*CLOCKS_PER_SEC;
  while (clock() < end) ;
}

Would it only be CPU waste.

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Multiserver, crash on many connections
« Reply #5 on: February 23, 2009, 10:50:24 am »
This will waste CPU time. Why not use sf::Sleep?

hajacken

  • Newbie
  • *
  • Posts: 11
    • View Profile
Multiserver, crash on many connections
« Reply #6 on: February 23, 2009, 05:43:37 pm »
Well that was my question, if SFML sleep function waste CPU. I don't think it but I am not so good at programming so it feels better to ask.

Ceylo

  • Hero Member
  • *****
  • Posts: 2325
    • View Profile
    • http://sfemovie.yalir.org/
    • Email
Multiserver, crash on many connections
« Reply #7 on: February 23, 2009, 06:45:05 pm »
It does not.
Want to play movies in your SFML application? Check out sfeMovie!

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Multiserver, crash on many connections
« Reply #8 on: February 23, 2009, 07:52:04 pm »
No, sf::Sleep doesn't waste CPU time. sf::Sleep's task is to give time to other processes in order to releave the CPU. ;)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

hajacken

  • Newbie
  • *
  • Posts: 11
    • View Profile
Multiserver, crash on many connections
« Reply #9 on: February 23, 2009, 08:54:26 pm »
ok, thanks.