How would having a non-blocking socket permit me to create a timeout function? Because I can't access the socket directly as it's private (unless I create a WinSock socket from scratch), and why would I want to even implement a looped iterator that would take more hassle than a selector with a blocking socket that uses wait?
We're talking about a IsReady function, not a ReceiveWithTimeout, right? So what I said is simply that IsReady is similar to Receive in non-blocking mode.
if (socket.isReady())
{
if (socket.receive(...) == sf::Socket::Done)
{
// process data
}
}
else
{
// do nothing
}
if (socket.receive(...) == sf::Socket::Done)
{
// process data
}
else
{
// do nothing
}
So you're mistakenly assuming that data is there to be read and receive should immediately try to receive data that isn't there? So if the connection fails (server side) and no data will be sent - receive shouldn't ignorantly assume data will be there. It's got to check first.
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.
sf::Http has frozen up several times because it assumes data is going to be sent when trying to receive data (which makes the 100% perfect connection fallacy - it won't get any additional data if the server terminates, and you can't reset the connection because receive is blocking).
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 :)
but Selector incurs overhead
No that much. And the only way to implement it (unless I completely rewrite SFML sockets) is to use a selector anyway.
The IsSocketReady would also solve that nonblocking socket connect issue - because people could call it after connect (which would permit it to work afterwards).
There's nothing that isReady would do that I can't do internally in connect. So this function is not needed to make connect work.
Please? I'm sure it can be useful.
I'm not. Please provide a relevant use case ;)
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 (http://stackoverflow.com/questions/6730460/why-is-non-blocking-socket-connect-so-slow) - 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) (http://cboard.cprogramming.com/networking-device-communication/59902-recv-blocks.html)... Especially with HTTP (http://stackoverflow.com/questions/1580614/http-client-blocks-on-recv).
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 (http://iono.jpl.nasa.gov/latest_rti_global.html), 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 (http://msdn.microsoft.com/en-us/library/windows/desktop/ms737625(v=vs.85).aspx)):
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.