We're talking about a IsReady function, not a ReceiveWithTimeout, right?
Correct. I'm just saying IsReady would be used within the (Blocking)ReceiveWithTimeout (as nonblocking requires additional complexity just to implement and can be... sporadic - either I can use a 'IsReady' and a 'BlockingReceive', or I have to write an iterative loop with a non-blocking socket that has a tendency
not to complete any work - you'd agree two simple functions is easier than a complicated iterative for/while loop that has to handle nonblocking issues).
Why? If there's no data, receive will simply tell you that there were nothing and return immediately. In other words, receive already checks for you, there's no need to have an extra function.
Receive doesn't return if there is no more data.
It blocks (the second post there even suggests using select to poll)...
Especially with HTTP.
I personally found receive froze up if called too many times (which is why I had to write a Receive with timeout function for my Telnet class - it uses the Selector Wait function to poll - and I'm now using a modified version of SFML 1.6 where the Http's SendRequest function's timeout actually applies to the receive by using... again, Selector with the Wait function). Since modifying both, the program thus far has
never blocked once (previously it would block after several hours). It's been running
continuously for at least 1-2 days now (previously I'd be lucky if it went 12 hours without a block).
receive returns an error status if the connection is broken. It can't block in this case.
If you noticed a strange behaviour, please make a bug report
Receive does not return if there is no additional data to be received (I can swap the DLLs around and wait until the program eventually blocks - of which the message will tell you what point it's reached - which can be narrowed down to SendRequest). It's not strange behaviour, as noted in the link above - HTTP will block if there is no additional data (but I find Receive blocks anyway if there is no additional data in other circumstances). If I get time, I'll draft an example piece of code (it's for 1.6 so I don't know if 2.0 solves this).
No that much. And the only way to implement it (unless I completely rewrite SFML sockets) is to use a selector anyway.
Selector incurs additional overhead by including an unnecessary (for this specific task) std::map - which I shouldn't need. In theory, you would only need a modified version of Wait - you shouldn't need to 'rewrite SFML sockets'. Besides - you can't implement Selector under a Socket - you'd likely get a circular dependency (A socket with a defined function trying to make a function call to a not-yet defined selector... or a defined selector making a function call that requires... a defined socket... eep!).
All I'm saying is this is copied and modified into 'IsReady()' for a socket.
unsigned int SelectorBase::Wait(float Timeout)
{
// Setup the timeout structure
timeval Time;
Time.tv_sec = static_cast<long>(Timeout);
Time.tv_usec = (static_cast<long>(Timeout * 1000) % 1000) * 1000;
// Prepare the set of sockets to return
mySetReady = mySet;
// Wait until one of the sockets is ready for reading, or timeout is reached
int NbSockets = select(myMaxSocket + 1, &mySetReady, NULL, NULL, Timeout > 0 ? &Time : NULL);
return NbSockets >= 0 ? static_cast<unsigned int>(NbSockets) : 0;
}
So the needed variables are self-contained, and only the socket itself is passed. It wouldn't 'defeat' selector's wait as selector is for multiple sockets (and intended to be more optimised for multiple sockets) - but an 'IsReady' would help with single sockets.
I'm not. Please provide a relevant use case
At present, I have a program that connects to a
website, it extracts the image link from the HTML, and then connects to the image link, downloads the image and writes it to file. The program then sleeps for approximately 4 minutes and 30 seconds (a new image is generated every 5 minutes, but this is to prevent it from 'missing' an image), before attempting to do this again.
Because the website does
not archive it's data, and this information is being used in an effort to see if ionospheric disturbances can predict earthquakes, it is important that as little of the data is lost, and the program must operate without human intervention (I cannot watch over it all day), this means it must:
A) Not block.
B) Avoid overly complicated code. (As it could fail whilst I am not around, and every moment wasted debugging complicated code is another image lost - the site doesn't archive).
B2) This means no complicated 'threaded' applications (which introduce race conditions and other nightmares).
B3) And no non-blocking sockets (as they introduce their own set of quirks and issues - which is even more complicated to implement than a simple poll-receive on a blocking socket).
Now I could implement a selector:
SelectorTCP Test;
Test.Add(SomeSocket);
while(Test.Wait(0.5) != 0)
{
SomeSocket.Receive(); //Yes, this doesn't go anywhere but it's pseudo-code
}
Test.Remove(); //Maybe this is unnecessary - but I can't be sure. For all I know Selector might close any sockets it has stored.
That's three unneccessary commands with the overhead of a std::map. Why not:
while(SomeSocket.IsReady(0.5))
{
SomeSocket.Receive();
}
Which could also be used to solve the non-blocking socket issue we were discussing via email earlier (one where
non-blocking sockets need select to complete the connection):
NonblockingSocket.Connect("fakeaddress.com",23);
while(!NonblockingSocket.IsReady(0));
Also, Zefz arrived at a similar conclusion I did in regards to an IsReady() type function (maybe not a standalone, as I'm still C in my thinking - perhaps a subset function of the individual socket itself), so perhaps such a solution has merit.