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

Author Topic: How to use non-blocking TCP?  (Read 5444 times)

0 Members and 1 Guest are viewing this topic.

P@u1

  • Jr. Member
  • **
  • Posts: 83
    • View Profile
How to use non-blocking TCP?
« on: May 30, 2011, 03:35:13 pm »
Hi,

I'm trying to use an sf::SocketTCP in non-blocking mode.
I want to use it like this:
Code: [Select]

if(/*socket is ready*/)
{
   socket.Send(...);
}
//if not ready continue the next main loop and send the date next time if the socket has become ready


How can I do this?
I need a method like
socket.IsReady(), but there is none.
Send() returns a status, but I want to check the status without actually sending anything.

Please help :-)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
How to use non-blocking TCP?
« Reply #1 on: May 30, 2011, 05:47:14 pm »
Sockets are always ready to send. The NotReady status is used only if you call Receive and there's no data available.
Laurent Gomila - SFML developer

P@u1

  • Jr. Member
  • **
  • Posts: 83
    • View Profile
How to use non-blocking TCP?
« Reply #2 on: May 30, 2011, 06:06:18 pm »
how can it be that they are always ready to send and they are still not blocking?

I think I can put in data much faster than it can be sent, so it would be nice to have a way to find out how fast data must be put in so that the sending process still catches up...
Otherwise I will have lots of data and it will be sent with a big delay and some queue (maybe deep in the operating system) will fill up more and more.

Any suggestions?

xazax

  • Guest
How to use non-blocking TCP?
« Reply #3 on: May 30, 2011, 06:35:41 pm »
I wrote a class for that, you may check it out.

http://www.assembla.com/code/Xazax/subversion/nodes/Snippets/network.cpp?rev=42
http://www.assembla.com/code/Xazax/subversion/nodes/Snippets/network.h?rev=42

I'm not an experienced C++ coder, so it may not be perfect, but it worked for me.

Usage:

http://pastebin.com/6sPwcFxw

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
How to use non-blocking TCP?
« Reply #4 on: May 30, 2011, 06:45:31 pm »
Quote
how can it be that they are always ready to send and they are still not blocking?

Technically you're right, if you send data at a very high rate the socket won't be able to catch up and data will start to be queued.

The implementation should be able to handle this, so I guess that Send() will return NotReady as well if the socket send buffer is not empty (or full).  Honestly this has never really been tested. But sorry for my previous answer that was quite wrong :)

So you could do
Code: [Select]
if (socket.Send(...) == sf::Socket::NotReady)
{
    try again later
}
else
{
    ok, data sent
}
Laurent Gomila - SFML developer

P@u1

  • Jr. Member
  • **
  • Posts: 83
    • View Profile
How to use non-blocking TCP?
« Reply #5 on: May 30, 2011, 06:59:01 pm »
Ok, thank you for your help, I will do some experiments now.

But it would be much nicer to be able to poll the status like
Code: [Select]

if(socket.GetStatus() == Socket::Done)
{
   //put in new date
}


The problem is that with you approach I always have to prepare a new packet without knowing if I will be able to sent it.

And does NotReady in this case mean that it will be sent later, or that it wont be sent at all?

And how does non-blocking io work for receiving?
I would try it like this:
Code: [Select]

sf::Packet toReceive;
socket >> receive;
if(!toReceive)
{
    //packet invalid, try again later...
}

Does it work like this?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
How to use non-blocking TCP?
« Reply #6 on: May 30, 2011, 08:04:15 pm »
Quote
The problem is that with you approach I always have to prepare a new packet without knowing if I will be able to sent it.

If the socket is ready you'll send your packet, so it has to be ready anyway, right? Is it really a problem for you?

Quote
And does NotReady in this case mean that it will be sent later, or that it wont be sent at all?

It means that it's not sent at all.

Quote
And how does non-blocking io work for receiving?

Nothing is returned to you as long as NotReady is returned.
Code: [Select]
sf::Packet packet;
sf::Socket::Status status = socket.Receive(packet);
if (status == sf::Socket::NotReady)
    // nothing received, try again later
else if (status == sf::Socket::Done)
    // ok, data received
else if (status == sf::Socket::Error)
    // error
else if (status == sf::Socket::Disconnected)
    // disconnected
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
How to use non-blocking TCP?
« Reply #7 on: May 30, 2011, 10:09:13 pm »
That's where message queues come in. Especially for larger streams (like file downloads/uploads) it's nearly guaranteed that write operations on your socket will block (or in case you set up your sockest to be non-blocking, returning without sending data).

The usual attempt is to fill a message queue (could be as easy as std::queue with some smart pointers to lower memory copy operations when delaying a packet) and work it down while the socket is ready to send.

 

anything