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

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Jungletoe

Pages: 1 ... 6 7 [8] 9
106
Network / Re: TCP Lag Reduction Techniques?
« on: April 10, 2013, 04:31:21 am »
Ok, having more problems. It's now sending the packets in order, but it's really buggy (it corrupts the packets). Also, the receive is also not working sometimes for those with bad ping and connection times.

How I handle dropped packets:

struct droppedPacket
{
        std::list<sf::Packet*> spack;
        sf::Int32 connectorID;
};

void NetworkManager::addDroppedPacket(sf::Packet* spack, sf::Int32 connectorID)
{
        bool found = false;
        for(sf::Int32 i = 0; i < droppedPackets.size(); i++)
        {
                if(droppedPackets[i].connectorID == connectorID)
                {
                        found = true;
                        droppedPackets[i].spack.push_front(spack);
                }
        }

        if(!found)
        {
                droppedPacket dp;
                dp.spack.push_back(spack);
                dp.connectorID = connectorID;
                droppedPackets.push_back(dp);
        }
}

void NetworkManager::retryDroppedPackets()
{
        for(sf::Int32 i = 0; i < droppedPackets.size(); i++)
        {
                Connector* con = getConnectorWithID(droppedPackets[i].connectorID);

                if(con != NULL)         //      client still online
                {
                        sf::Socket::Status status = con->socket.send(*droppedPackets[i].spack.back());

                        if(status == sf::Socket::Done)
                        {
                                //      packet sent correctly!
                                delete droppedPackets[i].spack.back();
                                droppedPackets[i].spack.pop_back();

                                if(droppedPackets[i].spack.empty())
                                        droppedPackets.erase(droppedPackets.begin() + i);
                        }

                        else if(status == sf::Socket::Disconnected)
                        {
                                ent::playerHandler.handleDisconnect(ent::connectors[i]->getID());
                        }

                        else
                        {
                                //      Packet did not send correctly
                        }
                }

                else    //      client disconnected
                {
                        while(!droppedPackets[i].spack.empty())
                        {
                                delete droppedPackets[i].spack.back();
                                droppedPackets[i].spack.pop_back();
                        }

                        droppedPackets.erase(droppedPackets.begin() + i);
                }
        }
}

bool NetworkManager::doesConnectorHaveDroppedPacket(sf::Int32 connectorID)
{
        for(sf::Int32 i = 0; i < droppedPackets.size(); i++)
        {
                if(droppedPackets[i].connectorID == connectorID)
                        return true;
        }
        return false;
}
 


How I handle the initial send:

bool Connector::sendPacket(sf::Packet* spack)
{
        if(!ent::networkManager.doesConnectorHaveDroppedPacket(ID))
        {
                sf::Socket::Status status = socket.send(*spack);

                if(status == sf::Socket::Done)
                {
                        //      packet sent correctly!
                        return true;
                }

                else
                {
                        sf::Packet* spack2 = new sf::Packet(*spack);
                        ent::networkManager.addDroppedPacket(spack2, ID);
                        return false;
                }
        }

        else
        {
                sf::Packet* spack2 = new sf::Packet(*spack);
                ent::networkManager.addDroppedPacket(spack2, ID);
                return false;
        }
}
 


How I handle receives:

void NetworkManager::recPackets()
{
        Connector* newConnector = new Connector;
        newConnector->socket.setBlocking(false);
        newConnector->player = NULL;

        if(listener.accept(newConnector->socket) == sf::Socket::Done)
        {
                //      Adds a new client to client list
                maxConID += 1;
                newConnector->setID(maxConID);
                ent::connectors.push_back(newConnector);
        }

        else
        {
                //      Nothing we can do...
                delete newConnector;
        }


        //      The listener socket is not ready, test all other sockets
        for(sf::Int32 i = 0; i < ent::connectors.size(); i++)
        {
                sf::Packet packet;
                sf::Socket::Status status = ent::connectors[i]->socket.receive(packet);

                if(status == sf::Socket::Done)
                {
                        ent::connectors[i]->logClock.restart();

                        sf::Uint32 packetCode;
                        packet >> packetCode;

                        handlePacket(packetCode, packet, ent::connectors[i]->getID());
                }

                else if(status == sf::Socket::Disconnected)
                {
                        ent::playerHandler.handleDisconnect(ent::connectors[i]->getID());
                }

                else if(status == sf::Socket::Error)
                {
                        std::cout << "NetworkingError";
                }

                else if(status == sf::Socket::NotReady)
                {
                        //      Not ready
                        //std::cout << "not ready";
                }
        }
}
 


Again, this (mostly) only occurs when the other connector has a bad connection and high ping times. Know of any problems with this?

107
Network / Re: TCP Lag Reduction Techniques?
« on: April 06, 2013, 11:57:50 pm »
The essence of this thread should be condensed and put somewhere into the SFML networking tutorials ;)

Hahaha agreed!

Anyways, with my new solution, it won't send the packets in order, resulting in a lot of problems. I'm going to have to put a std::list inside of the "droppedPackets" struct. I'll first check if the specific connector has any pending packets, and if it does, I'll add a packet into the list of packets it has to send first, that way it's always in order.

108
Network / Re: TCP Lag Reduction Techniques?
« on: April 06, 2013, 10:41:39 pm »
I don't know what your sending code looks like, but you are required to check the status code returned from the send() method as well. If it returns NotReady, you need to reattempt to send the data at a later time. If it returns Error or anything other than Done... well... you need to handle it as well ;).

THAT IS THE PROBLEM! I KNEW IT!

Okay... I'll try to fix this. I guess I'll put all "NotReady" packets inside of a vector and have the server cycle through it and attempt to resend it every frame.

109
Network / Re: TCP Lag Reduction Techniques?
« on: April 06, 2013, 10:19:52 pm »
The thing is that all of the packets are being sent, just some aren't being received. I asked around, and it seems that the worse connection that somebody has, the more packets don't get sent to them.

Could bad connections cause packets to be dropped with non-blocking networking setups?\

EDIT:
I found this topic and it seems to have a similar problem... http://en.sfml-dev.org/forums/index.php?topic=3363.0
I don't understand what "polling" the socket means though.

EDIT 2:
So I think on the send() function, I should handle NOTREADY somehow? What should I do? I'm 99% sure that this is the root of my problems.

110
Network / Re: TCP Lag Reduction Techniques?
« on: April 06, 2013, 08:52:08 am »
Ok, I changed the networking around and people are having a lot of problems. Other people seem to have their clients not getting packets, and my packets that are sent to me are either distorted or not coming through.

Here is my receive packets function which is called every frame:
void NetworkManager::recPackets()
{
        Connector* newConnector = new Connector;
        newConnector->socket.setBlocking(false);
        newConnector->player = NULL;

        if(listener.accept(newConnector->socket) == sf::Socket::Done)
        {
                //      Adds a new client to client list
                maxConID++;
                newConnector->setID(maxConID);
                ent::connectors.push_back(newConnector);
        }

        else
        {
                //      Nothing we can do...
                delete newConnector;
        }


        //      The listener socket is not ready, test all other sockets
        for(sf::Int32 i = 0; i < ent::connectors.size(); i++)
        {
                sf::Packet packet;
                sf::Socket::Status status = ent::connectors[i]->socket.receive(packet);

                if(status == sf::Socket::Done)
                {
                        sf::Uint32 packetCode;
                        packet >> packetCode;

                        handlePacket(packetCode, packet, ent::connectors[i]->getID());
                }

                else if(status == sf::Socket::Disconnected)
                {
                        ent::playerHandler.handleDisconnect(ent::connectors[i]->getID());
                }

                else if(status == sf::Socket::Error)
                {
                        std::cout << "NetworkingError";
                }

                else if(status == sf::Socket::NotReady)
                {
                        //      Not ready
                }
        }
}
 

and my send packets function:
void NetworkManager::sendPacket(sf::Packet* pack, sf::Int32 connectorID, bool delPacket)
{
        if(getConnectorWithID(connectorID) != NULL)
        {
                Connector* c = getConnectorWithID(connectorID);
                if(c != NULL)
                        c->sendPacket(pack);
        }

        if(delPacket)
        {
                delete pack;
        }
}
 

Why are some packets distorted/missing and why can people from other computers not get all of the packets I'm sending them (I have no problem connecting with 2 clients at the same time on my PC besides the occasional distortion or packet drop).

111
Network / Re: TCP Lag Reduction Techniques?
« on: April 06, 2013, 01:25:48 am »
Ok, one quick question before I actually go ahead and do all of this:
Is there an example of a non-blocking setup? I've seen the example of a blocking setup in the selector documentation, but I can't find one for non-blocking.

112
Network / Re: TCP Lag Reduction Techniques?
« on: April 05, 2013, 10:17:46 pm »
I've seen servers employ threading in many ways. Most of them thread their database accesses because as I already said, at medium to high load, waiting for the DB calls to return takes too long to ensure a decent framerate. If you didn't notice yet, MMORPG developers also tend to separate their worlds into "zones" or "instances" in order to split the game state up into manageable pieces. I don't know the details but I'd say that it is a good idea to just have a single thread per game state. Any more than that and they would fight over resources to the point that you have no benefit and are left with the overhead of the extra idle thread.

I broke up the game data into "chunks". There is a single "world" in my game, but it's broken down into chunks for easier loading. Object and map chunks are 20x20 tiles. Each map tile contains 1 short, and each object tile contains 2 shorts. They're loaded through the C binary loading functions. I also load various player files and crate/storage data, but not on a per-chunk basis (both are handled on a per-request basis).

The thing is, I want the server to be able to handle 1000+ players easily. I don't see how I could single-thread this without it lagging to hell every time I get over 20 people concurrently online.


get rid of your spikes ;)

How would that help? Wouldn't it just be running the same processes?

EDIT:
Wouldn't I also have to make it non-blocking?

113
Network / Re: TCP Lag Reduction Techniques?
« on: April 05, 2013, 06:33:04 am »
What if I have a thread that handles the packets and another one that receives them from the selector? The selector thread would simply dump all of the unprocessed packets into a vector of packets while the handler thread would pick up those packets and do something with them.

That way, it wouldn't get frozen up and delay connections from being acknowledged and stuff.

114
Network / Re: TCP Lag Reduction Techniques?
« on: April 05, 2013, 04:30:01 am »
Well your usage of mutexes in that snippet is also really strange. Do you have multiple recPackets threads? That's not such a good idea since you only protect the Selector with a mutex when a new connection is accepted and when a connection disconnects.

There is only one recPackets thread. I actually have a global mutex which locks up the whole program every time it receives a packet it needs to handle or needs to execute the worker thread. It's extremely inefficient as it is, and I really need to redo it. Without the global mutex, everything kept getting deadlocked.

115
Network / Re: TCP Lag Reduction Techniques?
« on: April 04, 2013, 10:08:06 pm »
Ok, I changed that, but I'm still getting spikes.

116
Network / Re: TCP Lag Reduction Techniques?
« on: April 02, 2013, 07:08:10 am »
Maybe you could provide code snippets. They would provide more information than the questions in your first post.

Hmm ok. What snippets do you need exactly?

Here is my server-sided "receive packets" function:

void NetworkManager::recPackets()
{
        // Receive a message from the client
        while(running)
        {
                //      Wait for data on any incoming socket
                if(Selector.wait(sf::milliseconds(250)))
                {
                        //      Test the listener
                        if(Selector.isReady(listener))
                        {
                                maxConID++;
                                Connector* newConnector = new Connector;
                                newConnector->player = NULL;
                                newConnector->setID(maxConID);
                               
                                if(listener.accept(newConnector->socket) == sf::Socket::Done)
                                {
                                        mu::lockMutexes();
                                        mutex.lock();
                                        //      Adds a new client to client list
                                        ent::connectors.push_back(newConnector);

                                        //      Add a new client to the selector so we will be
                                        //      notified if we recieve something from it
                                        Selector.add(newConnector->socket);
                                        mutex.unlock();
                                        mu::unlockMutexes();
                                }

                                else
                                {
                                        //      Nothing we can do...
                                }
                        }

                        else
                        {
                                //      The listener socket is not ready, test all other sockets
                                for(sf::Int32 i = 0; i < ent::connectors.size(); i++)
                                {
                                        sf::TcpSocket &client = ent::connectors.at(i)->socket;
                                        if(Selector.isReady(client))
                                        {
                                                //      The client has some data, we can recieve it
                                                sf::Packet packet;
                                                if(client.receive(packet) == sf::Socket::Done)
                                                {
                                                        sf::Uint32 packetCode;
                                                        packet >> packetCode;

                                                        mu::lockMutexes();

                                                        handlePacket(packetCode, packet, ent::connectors[i]->getID());

                                                        mu::unlockMutexes();
                                                }

                                                else if(client.receive(packet) == sf::Socket::Disconnected)
                                                {
                                                        mu::lockMutexes();

                                                        mutex.lock();
                                                        ent::playerHandler.handleDisconnect(ent::connectors[i]->getID());
                                                        mutex.unlock();

                                                        mu::unlockMutexes();
                                                }

                                                else if(client.receive(packet) == sf::Socket::Error)
                                                {
                                                        std::cout << "NetworkingError";
                                                }
                                        }
                                }
                        }
                }
        }
}
 

The handlePacket() function takes a packet, unloads it, and does something with the data (puts in some movement requests, tile changes, etc).

The mu::lock/unlockMutexes() functions lock all the global mutexes to prevent deadlock and crashes. Yes, it's a pain to do multithreading. I have to lock everything every time a thread accesses some sort of data within the program. I'm beginning to wonder if multi-threading was even worth it.

The thing I don't understand is why it doesn't just freeze up completely (because of deadlock or failing to unlock a mutex)-- it always resumes normal work receiving packets/handling data/saving after about 10-30 seconds (in some bad cases, longer). I also tested to make sure that it didn't have to do with the loading/saving aspects of the program and it seemed to be normally timed. The thing is that it only freezes like this when there are multiple players online (all of them seem to be doing normal tasks in the game-- nothing out of the ordinary that would execute some long function).

If you want to have an extended look at it, you can add me on Skype (brady.welch).

117
Network / Re: TCP Lag Reduction Techniques?
« on: April 02, 2013, 03:16:59 am »
Ok, I reduced the size of the packets. Still no luck. The server still pauses/freezes for 10-30 seconds on ZwWaitForSingleObject.

118
Network / Re: TCP Lag Reduction Techniques?
« on: March 30, 2013, 10:40:15 pm »
Int in like 32bit standard integers?
Because one of these 20*20 packets would be 20*20*32/8 = 1600 bytes.
The 30*30 packets would be 30*30*32/8 = 3600 bytes.

Also you are sending the character name with each move?
If so, that is alot of bandwidth wasted.

If you need a way to distinguish the different move request for each character, you should consider using a sf:Uint8 or sf:Uint16 as an ID number, and give every single player a unique ID for that playsession, which allows every client to know which character entity is moved by each move request.

You should try to make packets as small as possible, as 1kb packets send to 20 people, perhaps multiple times per seconds, takes alot of bandwidth pretty fast.

And while most home connections have a good downstreams, the upstreams are often limited in speed.

Hmm ok... I already have IDs for animals, so Ill just switch that code over to the players. That should be a simple fix.

And yes-- the 32bit ints.

So should I break down these packets? Would that solve anything? And is it just due to the fact that Im hosting it from my house network, because games like Minecraft don't seem to have that problem with 11 people.

119
Network / Re: TCP Lag Reduction Techniques?
« on: March 30, 2013, 10:13:25 pm »
May I ask what exactly are you sending there?
5-20s sounds like you are sending something huge.

Map chunks (about 20x20 ints), object chunks (can be anything from 0 ints to 30x30-- although rarely that high), and player movements (player name string, int x, int y, bool running) in which a for loop adds multiple player positions to the same packet if the player has moved.

The player movement packets take the longest to send if there are 2+ players all putting in a movement request at once, which is where the problem arises.

120
Network / TCP Lag Reduction Techniques?
« on: March 30, 2013, 09:14:30 pm »
Hi, I'm developing an sandbox ORPG called Colonies.

As my game has progressed, we have gotten upwards of 20 players constantly on at once. With this new traffic, there is also a lot of lag that has followed. After optimizing everything except the networking backend, I came to the realization that the lag was coming from sending packets.

The game can suddenly freeze for 5-20 seconds at worst. I profiled the threads and noticed that it was getting held up at "zwwaitforsingleobject" inside of the send packet function.

-What are some common techniques to reduce the sending lag?
-Would breaking down the packets into smaller ones reduce the lag or have no effect since SFML does this anyways (I've noticed that larger packets take longer to send)?
-Does adding a timeout to the selector effect the timeout of the send? Do I need to have the selector in a different thread from the "sendPacket" functions in order for the timeout to work?

Thanks,
Jungle

Pages: 1 ... 6 7 [8] 9