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

Author Topic: Newbie Problem - TCP server lagging. (problems with sending?)  (Read 4756 times)

0 Members and 1 Guest are viewing this topic.

malatin3

  • Newbie
  • *
  • Posts: 5
    • View Profile
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?
« Last Edit: June 27, 2013, 03:28:31 pm by malatin3 »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11033
    • View Profile
    • development blog
    • Email
Re: Newbie Problem - TCP server lagging. (problems with sending?)
« Reply #1 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.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

malatin3

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Newbie Problem - TCP server lagging. (problems with sending?)
« Reply #2 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;
}

malatin3

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Newbie Problem - TCP server lagging. (problems with sending?)
« Reply #3 on: September 19, 2013, 05:49:04 am »
was my code not compact? haha.. no ideas on whats going on?

Daffern

  • Newbie
  • *
  • Posts: 25
    • View Profile
    • Email
Re: Newbie Problem - TCP server lagging. (problems with sending?)
« Reply #4 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);
}

malatin3

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Newbie Problem - TCP server lagging. (problems with sending?)
« Reply #5 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?
« Last Edit: September 21, 2013, 08:03:20 pm by malatin3 »

Daffern

  • Newbie
  • *
  • Posts: 25
    • View Profile
    • Email
Re: Newbie Problem - TCP server lagging. (problems with sending?)
« Reply #6 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++;
                        }