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

Author Topic: best practices  (Read 3290 times)

0 Members and 1 Guest are viewing this topic.

vro

  • Newbie
  • *
  • Posts: 44
    • View Profile
best practices
« on: May 29, 2012, 04:08:23 am »
Not code-specific, but I have a few questions about a simple game server for a 2d shooter:

-From what I understand, the Client's sockets should be non-blocking, as you you want the game to appear seamless with receiving updates.
Should the server be non-blocking too? Or since all it does it handle requests for info, etc. it's OK to have the server blocking and the client non-blocking, right?

-On the client, should I run the socket stuff in a separate thread? Or since it's going to be non-blocking is that unnecessary?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: best practices
« Reply #1 on: May 29, 2012, 08:06:17 am »
Either you block in a separate thread, or you don't block in the main thread.
Laurent Gomila - SFML developer

vro

  • Newbie
  • *
  • Posts: 44
    • View Profile
Re: best practices
« Reply #2 on: May 31, 2012, 10:27:52 pm »
I could use some help figuring this out, I switched over to SFML 2.0 yesterday, and I've got a basic client/server set up using threads and the selector code from the documentation. I've searched the forums, google, the doc, wiki, etc, and I still can't figure this out.

So all was well until I added functionality for a client to send the server a "quit" message so the server knows to tell the other clients. What happens is I can connect with the client and then quit twice, but the 3rd time it all goes haywire and I can't narrow it down.
Here is the relevant code:
Server
Quote
void Server::runThread()
{
    if (!TCPListener.listen(40104))
    {
        // Error..
    }
    Selector.add(TCPListener);

    bool threadRunning = true;
    while (threadRunning)
    {
        receivePacket.clear();
        sendPacket.clear();
        if (Selector.wait(sf::Time::Zero))
        {
            //test the listener
            if (Selector.isReady(TCPListener))
            {
                sf::TcpSocket* client = new sf::TcpSocket;
                if (TCPListener.accept(*client) == sf::Socket::Done)
                {
                    clients.push_back(client);
                    Selector.add(*client);
                }
            }
            else //listener not ready, test all other sockets (the clients)
            {
                for (list<sf::TcpSocket*>::iterator it = clients.begin(); it != clients.end(); it++)
                {
                    sf::TcpSocket& client = **it;
                    if (Selector.isReady(client))
                    {
                        if (client.receive(receivePacket) == sf::Socket::Done)
                        {
                            sf::Int8 action = 0;
                            receivePacket >> action;

                            cout << "action received: " << (short)action << endl;

                            switch ((short)action)
                            {
                                case JOIN: //1
                                    playerJoin(client);
                                    break;
                                case UPDATE: //2
                                    break;
                                case MESSAGE: //3
                                    break;
                                case QUIT: //4
                                    playerQuit(client);
                                    break;
                                default:
                                    cerr << "Invalid packet received." << endl;
                                    break;
                            }
                        }
                    }
                }
            }
        }
    }
}
Quote
void Server::playerQuit(sf::TcpSocket &Socket)
{
    ///Kill socket
    list<sf::TcpSocket*>::iterator it = clients.begin();
    while (it != clients.end())
    {
        if (*it == &Socket)
        {
            delete *it;
            it = clients.erase(it);
            Selector.remove(Socket);
        }
        else
            it++;
    }
    ///tell other players
    sendPacket.clear();
    for (list<sf::TcpSocket*>::iterator it = clients.begin(); it != clients.end(); it++)
    {
        sf::TcpSocket& client = **it;
        sf::Int8 action = JOIN;
        string message = "A player has quit.";
        sendPacket << action << message;
        if (client.send(sendPacket) != sf::Socket::Done)
        {
            // Error
        }
    }
}


Client
Quote
Client::~Client()
{
    sendPacket.clear();
    sf::Int8 action = QUIT;
    sendPacket << action;
    if (TCPSocket.send(sendPacket) != sf::Socket::Done)
    {
        // Error
    }
    threadRunning = false;
    thread.wait();
}
« Last Edit: May 31, 2012, 10:29:32 pm by vro »

vro

  • Newbie
  • *
  • Posts: 44
    • View Profile
Re: best practices
« Reply #3 on: June 01, 2012, 09:29:44 am »
ended up switching over to UDP.
Everythings working now :/
I think removing from the selector might have been causing it, but more than likely probably a mistake on my part.