SFML community forums

Help => Network => Topic started by: malatin3 on June 27, 2013, 11:07:36 am

Title: Newbie Problem - TCP server lagging. (problems with sending?)
Post by: malatin3 on June 27, 2013, 11:07:36 am
I'm trying to set up a simple TCP client/server where a bunch of people can move blocks around a screen. The problem I'm getting right now is, whenever I have more than one client broadcasting location data, the delay between when the server receives the data and between when it sends it back to the clients gradually increases. One client is fine but it quickly builds up to delays that last up to 10 or more seconds.

If I tell the server to stop sending information back to the clients it runs normally... so I'm guessing that the problem lies somewhere with how I'm sending data.

I've tried hugely lowering the frame rate of my client and it didn't really have any effect on the lag. The packet sizes are also normally under 100 bytes.

Any ideas where I should start looking?
Title: Re: Newbie Problem - TCP server lagging. (problems with sending?)
Post by: eXpl0it3r on June 27, 2013, 11:22:21 am
You should rather minimize your codebase and post a complete and minimal example. ;)
There are also some highlighted points in the SFML FAQ, which might help.
Title: Re: Newbie Problem - TCP server lagging. (problems with sending?)
Post by: malatin3 on June 27, 2013, 03:31:30 pm
I tried to make a minimal version. Should work.. somewhat ^^;

I'm not sure if this illustrates the problem properly but... if several clients are connected the server starts to chug.

Server Code
#include <SFML/Network.hpp>
#include <iostream>
#include <deque>

struct PlayerCharacter
{
    int x;
    int y;
};

struct User
{
    sf::TcpSocket* socket;
    PlayerCharacter* player;
    int id;
};

void receivePacket(sf::Packet *packet, PlayerCharacter *pc, std::deque<std::string> *chat)
{

    int packetid;
    *packet >> packetid;

    //Updates character location
    if (packetid == 2)
    {
        int temp_xchange;
        *packet >> temp_xchange;
        int temp_ychange;
        *packet >> temp_ychange;
        int packet_number;
        *packet>> packet_number;

        pc->x = (pc->x + temp_xchange);
        pc->y = (pc->y + temp_ychange);

        std::cout << pc->x << "_" << pc->y << "_" << packet_number << std::endl;
    }
}

void updateClients(std::deque<std::string> *chat, std::vector<User> *clients)
{
    sf::Packet out_packet;

    //If there is chat in the queue. It will pop and send it to the clients.
    if (chat->size() > 0)
    {
        out_packet << 1;
        std::string temp_string;
        temp_string = chat->front();
        chat->pop_front();
        out_packet << temp_string;

        for (unsigned int i = 0; i < clients->size(); i++)
        {
            clients->at(i).socket->send(out_packet);
        }
    }

    //Sends player data to other players
    for (unsigned int i = 0; i < clients->size(); i++)
    {
        out_packet << 2;
        out_packet << clients->at(i).id;
        out_packet << clients->at(i).player->x << clients->at(i).player->y;
        clients->at(i).socket->send(out_packet);
    }
}

int main()
{
    std::deque<std::string> chatLog;
    sf::TcpListener listener;
    listener.listen(7338);
    std::vector<User> clients;
    sf::SocketSelector selector;
    selector.add(listener);

    while (true)
    {
        if (selector.wait())
        {
            if (selector.isReady(listener))
            {
                sf::TcpSocket* client = new sf::TcpSocket;
                if (listener.accept(*client) == sf::Socket::Done)
                {
                    int temp_id;
                    bool unique_id;
                    do
                    {
                        unique_id = true;
                        temp_id = rand() % 10000000;
                        for (unsigned int i = 0; i < clients.size(); i++)
                        {
                            if (temp_id == clients[i].id)
                            {
                                unique_id = false;
                            }
                        }
                    }
                    while(unique_id == false);

                    PlayerCharacter temp_player;
                    User temp_user = {client, &temp_player, temp_id};
                    clients.push_back(temp_user);

                    std::cout << "New client connected: " << client->getRemoteAddress() << std::endl;
                    selector.add(*client);
                }
                else
                {

                    delete client;
                }
            }
            else
            {
                for (unsigned int i = 0; i < clients.size(); i++)
                {
                    if (selector.isReady(*clients.at(i).socket))
                    {
                        sf::Packet packet;
                        sf::Socket::Status status = clients.at(i).socket->receive(packet);
                        if (status == sf::Socket::Done)
                        {
                            receivePacket(&packet,clients.at(i).player, &chatLog);
                        }
                        else if (status == sf::Socket::Disconnected)
                        {
                            std::cout<<"Client disconnected."<<std::endl;
                            selector.remove(*clients.at(i).socket);
                            clients.at(i).socket->disconnect();
                            delete(&clients.at(i).socket);
                            clients.erase(clients.begin()+ i);
                            i--;
                            std::cout<<"Clients currently connected: "<<clients.size()<<std::endl;
                        }
                    }
                }
            }
        }
        updateClients(&chatLog, &clients);
    }
    return 0;
}
 

And here's the client code that I threw together..
#include <SFML/Network.hpp>
#include <SFML/Graphics.hpp>
#include <iostream>
#include <sstream>
#include <deque>

struct PlayerCharacter
{
    int id;
    int x;
    int y;
};

int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "Eris v0.001");
    window.setFramerateLimit(30);
    sf::TcpSocket socket;
    socket.setBlocking(false);
    sf::Packet in_packet;
    std::vector<PlayerCharacter> playerlist;
    int packetnumber = 0;

    sf::IpAddress server("localhost");
    if (socket.connect(server, 7338) != sf::Socket::Done)
    {
        //something
    }

    while (window.isOpen())
    {
        if (socket.receive(in_packet) == sf::Socket::Done)
        {
            int packet_id;
            in_packet >> packet_id;
            if (packet_id == 2)
            {
                int player_id;
                in_packet >> player_id;
                std::cout<<player_id<<"_";
                int temp_x;
                in_packet >> temp_x;
                std::cout<<temp_x<<"_";
                int temp_y;
                in_packet >> temp_y;
                std::cout<<temp_y<<"_"<<std::endl;

                bool exists = false;
                for (unsigned int i = 0; i < playerlist.size(); i++)
                {
                    if (playerlist[i].id == player_id)
                    {
                        exists = true;
                        playerlist[i].x = temp_x;
                        playerlist[i].y = temp_y;
                    }
                }
                if (exists == false)
                {
                    PlayerCharacter temp_player = {player_id, temp_x, temp_y};
                    playerlist.push_back(temp_player);
                }
            }
        }

        packetnumber++;
        //sends location data
        sf::Packet out_packet;
        out_packet << 2 << 0 << 0 << packetnumber;
        std::cout<<"SENT:" << packetnumber << std::endl;
        socket.send(out_packet);

        window.clear();
        window.display();
    }

    return 0;
}
Title: Re: Newbie Problem - TCP server lagging. (problems with sending?)
Post by: malatin3 on September 19, 2013, 05:49:04 am
was my code not compact? haha.. no ideas on whats going on?
Title: Re: Newbie Problem - TCP server lagging. (problems with sending?)
Post by: Daffern on September 20, 2013, 03:37:34 pm
Had this same problem myself.

In this piece of code:

 sf::Socket::Status status = clients.at(i).socket->receive(packet);
if (status == sf::Socket::Done)
 {
       receivePacket(&packet,clients.at(i).player, &chatLog);
}

Try this instead:

while (clients.at(i).socket->receive(packet) = sf::Socket::Done){
           receivePacket(&packet,clients.at(i).player, &chatLog);
}
Title: Re: Newbie Problem - TCP server lagging. (problems with sending?)
Post by: malatin3 on September 21, 2013, 07:36:44 pm
 ;D ;D ;D ;D

That did the trick! Thanks a ton man.



I love you.

Edit: How did you handle disconnects with the while loop?
Title: Re: Newbie Problem - TCP server lagging. (problems with sending?)
Post by: Daffern on September 21, 2013, 11:27:55 pm
Happy to help! :)

I did this in the receive loop(right after the code i posted). Havent tested it in a while, but it worked the last time.
if (socket.receive(packet) == sf::Socket::Disconnected)
                        {
                                std::cout<<"Client disconnected"<<std::endl;
                                std::cout<<"list size: "<<clients.size();
                                selector.remove(socket);
                                socket.disconnect();
                                delete *it;
                                it = clients.erase(it);

                                std::cout<<" then: "<<clients.size()<<std::endl;
                        }
                        else
                        {
                                it++;
                        }