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

Author Topic: Non-Blocking TCP Freeze [Fixed]  (Read 31700 times)

0 Members and 1 Guest are viewing this topic.

rgrant1993

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Sound freezes
« Reply #45 on: June 03, 2013, 11:02:03 pm »
you should think about tidying up that code first.. until then im not even going to bother to look at it.

Jungletoe

  • Full Member
  • ***
  • Posts: 132
    • View Profile
    • Email
Re: Sound freezes
« Reply #46 on: June 04, 2013, 01:11:38 am »
you should think about tidying up that code first.. until then im not even going to bother to look at it.

How much more clear can I make it? I commented it and provided a rational on what it does.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sound freezes
« Reply #47 on: June 04, 2013, 08:12:57 am »
As I told ou in PM, you should provide a complete and minimal example that reproduces the problem, and only that. Don't try to stay in the context of your original application, rewrite it from scratch.

How are we supposed to test or analyze an incomplete piece of code extracted from a big project that we know nothing about?
Laurent Gomila - SFML developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Sound freezes
« Reply #48 on: June 04, 2013, 04:15:44 pm »
I can see why this it is difficult to reproduce this using a minimal example. The problem obviously doesn't arise from the way SFML implemented packets or TCP communication but from side effects which are difficult to determine and isolate. I assume Jungletoe is reporting about these problems while running the server software on only a single host and thus can only evaluate a single environment. I will test sending and receiving different packet sizes on multiple hosts at my disposal and see if I can come up with anything.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Jungletoe

  • Full Member
  • ***
  • Posts: 132
    • View Profile
    • Email
Re: Sound freezes
« Reply #49 on: June 04, 2013, 05:01:15 pm »
I assume Jungletoe is reporting about these problems while running the server software on only a single host and thus can only evaluate a single environment. I will test sending and receiving different packet sizes on multiple hosts at my disposal and see if I can come up with anything.

Awesome, thanks!

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Sound freezes
« Reply #50 on: June 04, 2013, 08:12:00 pm »
I just ran the tests pairwise between 3 servers and my home connection and nothing seems to go wrong. SFML can send and receive packets as large as 65000 bytes or packets around 2000 bytes in quick succession without anything being lost at the upper layers. As expected TCP was choking on the data rate a bit and retransmitting data a lot but none of this is noticeable to an application using SFML.

Here is the server/client code I used:
#include <SFML/Network.hpp>

int main() {
        sf::TcpListener listener;
        listener.listen( 4422 );
       
        sf::TcpSocket socket;
        listener.accept( socket );
       
        sf::Packet packet;
       
        while( !socket.receive( packet ) ) {
                socket.send( packet );
        }
       
        return 0;
}
 
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <SFML/Network.hpp>

int main() {
        sf::TcpSocket socket;
        socket.connect( "12.34.56.78", 4422 );

        for( int size = 100; size < 65000; size += 100 ) {
                std::cout << "Probing size: " << size << "\n";

                sf::Packet send_packet;
                sf::Packet recv_packet;

                for( int i = 0; i < size; i += sizeof( int ) ) {
                        int value = rand();
                        send_packet << value;
                }

                socket.send( send_packet );
                socket.receive( recv_packet );

                if( ( send_packet.getDataSize() != recv_packet.getDataSize() ) ||
                    memcmp( send_packet.getData(), recv_packet.getData(), recv_packet.getDataSize() ) ) {
                        std::cout << "Data corruption!\n";
                        return 1;
                }
        }

        return 0;
}
 
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Jungletoe

  • Full Member
  • ***
  • Posts: 132
    • View Profile
    • Email
Re: Sound freezes
« Reply #51 on: June 05, 2013, 02:37:52 am »
Your snippet works perfectly, but this doesn't:

int main ( int argc, char *argv[] )
{
        sf::TcpSocket socket;
        socket.setBlocking(true);
        socket.connect("192.168.1.14", 41013);
        socket.setBlocking(false);
       
        for(sf::Int32 j = 0; j < 5; j++)
        {
                //      SEND
                {
                        sf::Packet pack;
                        for(sf::Int32 x = 0; x < 3000; x++)
                        {
                                sf::Int32 num = 1;
                                pack << num;
                        }
                        socket.send(pack);
                }

                std::cout << "Sent packet #" << j << "\n";
        }

        for(sf::Int32 j = 0; j < 5; j++)
        {
                //      REC
                {
                        sf::Packet pack;
                        socket.receive(pack);

                        for(sf::Int32 x = 0; x < 3000; x++)
                        {
                                sf::Int32 num;
                                pack >> num;

                                if(num != 1)
                                        std::cout << "corruption";
                        }

                        std::cout << "Recieved packet #" << j << "\n";
                }
        }

        system("PAUSE");
        return 0;
}
 

Just use the server from your example and use the above as the client.


Edit
Aaaaaand I just discovered the problem. Switching from blocking to non-blocking after connecting SEVERELY distorts packets. I thought non-blocking connect() doesn't work?

Edit 2
Non-blocking connect() does not work. It returns NotReady.

Edit 3
Related topic: http://en.sfml-dev.org/forums/index.php?topic=7435.0


Edit 4
This doesn't corrupt it. My bad-- one second please.

« Last Edit: June 05, 2013, 04:14:14 am by Jungletoe »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Sound freezes
« Reply #52 on: June 05, 2013, 03:07:20 am »
I think it is obvious it won't work? The whole program will finish execution in less than 1ms on a decent system because the sockets don't block and the data will have just left the network adapter... Also if you send that fast, you might even overflow the send buffer because there might be latency between your application and the operating system or hardware. You would have to check the return value for the send as well in that case to determine if the data was properly queued for sending.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Jungletoe

  • Full Member
  • ***
  • Posts: 132
    • View Profile
    • Email
Re: Sound freezes
« Reply #53 on: June 05, 2013, 03:12:49 am »
I think it is obvious it won't work? The whole program will finish execution in less than 1ms on a decent system because the sockets don't block and the data will have just left the network adapter... Also if you send that fast, you might even overflow the send buffer because there might be latency between your application and the operating system or hardware. You would have to check the return value for the send as well in that case to determine if the data was properly queued for sending.

Check the edits. The problem appears to be with the non-blocking connect.

Edit
Never mind, this appears to be the same issue. I misread what you said.
I did check the return value, as I showed here: http://en.sfml-dev.org/forums/index.php?topic=11221.0

Edit 2
So what do you suggest I do? I think I'm overflowing the receive buffer in the client because of all the data I'm sending extremely fast.
« Last Edit: June 05, 2013, 03:28:35 am by Jungletoe »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Sound freezes
« Reply #54 on: June 05, 2013, 05:03:17 am »
TCP will never "overflow" the receive buffer with data. When the buffer is full TCP congestion flow control will kick in and implicitly inform the sender that the destination system can't accept any more data. What that will result in is the sending side filling up as well. Once the sending side is filled up, the send() from your application should fail with an error or NotReady in SFML and indicate you should wait a bit and try again. Trust me, the TCP network stack is built in a very robust way. Even over really really crappy connections TCP will never silently drop data. The only place where data can be lost is in your code if you don't listen to what TCP is trying to tell you. If data loss is unavoidable TCP will at least try to notify you of it by closing the connection. In this case, which is also the only case where data loss can occur, you are informed of the error and should take the required action.

Here is some code showing what happens when the receiver doesn't remove the data from it's queue. It also shows how much data can be queued up on the system running the receiver.

Sender:
#include <iostream>
#include <string>
#include <SFML/Network.hpp>

int main() {
        sf::TcpSocket socket;
        socket.connect( "12.34.56.78", 4422 );
        socket.setBlocking( false );

        std::size_t count = 0;

        sf::Clock clock;

        while( true ) {
                sf::Packet packet;

                std::string s( "0", 2048 );

                packet << s;

                sf::Socket::Status status = socket.send( packet );

                if( status == sf::Socket::Done ) {
                        count += 2048;
                        std::cout << "Sent " << count << " bytes.\n";
                } else if( status == sf::Socket::Error ) {
                        std::cout << "Error\n";
                } else if( status == sf::Socket::Disconnected ) {
                        std::cout << "Disconnected\n";
                } else if( status == sf::Socket::NotReady ) {
                        std::cout << "NotReady\n";
                }

                if( clock.getElapsedTime() > sf::seconds( 5 ) ) {
                        return 0;
                }
        }

        return 0;
}
 

Receiver:
#include <iostream>
#include <SFML/Network.hpp>

int main() {
        sf::TcpListener listener;
        listener.listen( 4422 );
       
        sf::TcpSocket socket;
        listener.accept( socket );
       
        sf::sleep( sf::seconds( 10 ) );
       
        sf::Packet packet;
       
        std::size_t count = 0;
       
        while( !socket.receive( packet ) ) {
                count += packet.getDataSize();
        }
       
        std::cout << "Dequeued " << count << " bytes.\n";
       
        return 0;
}
 

Edit: If you need to take a break from coding you should watch a few good lecture videos about TCP. Here's one:
I had the opportunity to attend lectures and learn from my professors first hand :).
« Last Edit: June 05, 2013, 05:16:27 am by binary1248 »
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Jungletoe

  • Full Member
  • ***
  • Posts: 132
    • View Profile
    • Email
Re: Sound freezes
« Reply #55 on: June 05, 2013, 06:12:14 am »
After a lot of reviewing and labor, I can't reproduce the same errors again unless I use the exact networking structure I use in my project. Would it be okay if I posted it all here?

I will try to keep it as minimal as possible.
« Last Edit: June 05, 2013, 06:14:10 am by Jungletoe »

Jungletoe

  • Full Member
  • ***
  • Posts: 132
    • View Profile
    • Email
Re: Sound freezes
« Reply #56 on: June 05, 2013, 06:37:09 pm »
Ah ok, so after watching that video, the send() in the server will return NotReady if the receive buffer is full?

What if I already handle that? Here is my code for sending packets:
void Connector::sendPacket(sf::Packet* spack)
{
        if(packets.size() <= 0)
        {
                sf::Socket::Status status = socket.send(*spack);

                if(status == sf::Socket::NotReady || status == sf::Socket::Error)
                {
                        packets.push(*spack);

                        if(status == sf::Socket::Error)
                        {
                                std::cout << "E1E\n";
                        }
                }
        }

        else
        {
                packets.push(*spack);
        }
}
 

and if it pushes the packet back, it'll eventually return with the retryDroppedPackets() function and do this:
if(!ent::connectors[i]->packets.empty())
                {
                        sf::Socket::Status status = ent::connectors[i]->socket.send(ent::connectors[i]->packets.front());

                        if(status == sf::Socket::Done)
                        {
                                ent::connectors[i]->packets.pop();
                        }

                        if(status == sf::Socket::Error)
                        {
                                std::cout << "E1E\n";
                        }
                }
 


Also, when the send() buffer is full like you said, would it only stop sending packets to ONE socket (the socket it was sending to)? Not the sockets of every person connected to the server?


Edit
I just read this over on GameDev.net

Quote
If [send()] doesn't block, it will buffer whatever it can and return that length.

So could this be the problem? Could the send() just be stuck with the overflow of data? Is there any way to avoid this?
« Last Edit: June 05, 2013, 06:47:04 pm by Jungletoe »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Sound freezes
« Reply #57 on: June 06, 2013, 08:14:03 am »
Each connection has it's own buffers for sending and receiving. If one connection is stalled the others will not be affected.

I just read this over on GameDev.net
Quote
If [send()] doesn't block, it will buffer whatever it can and return that length.
So could this be the problem? Could the send() just be stuck with the overflow of data? Is there any way to avoid this?
There are only 2 things that can happen with your data when you call send(). Either it buffers it for sending, or it doesn't. It doesn't matter whether the remote host has space or not, it will still be buffered in the send buffer because this is required by TCP. When the data isn't buffered, the send() call either blocks if you are in blocking mode, or it returns NotReady in non-blocking mode. The send() call doesn't get "stuck".

Actually... I just noticed something in the SFML source code... going to investigate.

Edit: Yeah it seems there is a really nasty bug that is causing this ::). I'll start a separate thread when I get home today.
« Last Edit: June 06, 2013, 09:15:51 am by binary1248 »
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Jungletoe

  • Full Member
  • ***
  • Posts: 132
    • View Profile
    • Email
Re: Sound freezes
« Reply #58 on: June 06, 2013, 09:16:14 am »
I think delaying the sending of large packets quickly prevents the problem from happening.

EDIT:
Nope.
« Last Edit: June 06, 2013, 09:19:32 am by Jungletoe »

Jungletoe

  • Full Member
  • ***
  • Posts: 132
    • View Profile
    • Email
Re: Sound freezes
« Reply #59 on: June 06, 2013, 09:24:45 am »
Edit: Yeah it seems there is a really nasty bug that is causing this ::). I'll start a separate thread when I get home today.

Ah, finally!  :D