When I use a blocking socket with send/recv calls, the call will block
till the operation is completed. Supposing a recv call blocks for a
long time due to no data being sent from the peer, is there a way to
make the recv call return?
Currently I know of two options:
1. Setting the socket options for timeout using SO_RCVTIMEO /
SO_SNDTIMEO so that the call times out after a specified time if there
is no data available on the socket.
2. Use a select call with a timeout before the actual call to recv.
Is there any other way available for doing this? Also which one of the
above two is more efficient and is a better way to resolve the
mentioned problem.
I hope this is the right group to post this message. Any pointers will
be helpful.
Thanks in Advance!
Regards,
Jayaraghavendran.K
> Hi All,
>
> When I use a blocking socket with send/recv calls, the call will block
> till the operation is completed. Supposing a recv call blocks for a
> long time due to no data being sent from the peer, is there a way to
> make the recv call return?
AFAIK, not without rendering the socket unusable.
> Currently I know of two options:
>
> 1. Setting the socket options for timeout using SO_RCVTIMEO /
> SO_SNDTIMEO so that the call times out after a specified time if there
> is no data available on the socket.
Note that this solution renders the socket unusable. Once a timeout has
occurred, you're supposed to close the socket and start over, because the
data could be unreliable after that point.
This is similar to another alternative, which would be to close the socket
from another thread. That would cause recv to return with an error, but
of course closing the socket means you can't receive from it again.
> 2. Use a select call with a timeout before the actual call to recv.
For a blocking socket, this or one of the related functions
(WSAEventSelect, WSAAsyncSelect) is about the best you're going to do.
Note that even in this case, there's a possibility that when the socket is
signaled for readability, by the time you get to read it, it will no
longer be readable and the call to recv would block.
For that reason, I'd advise against using select, WSAEventSelect, and
WSAAsyncSelect with blocking sockets. Using blocking sockets runs the
risk of negating the whole point of using select/etc. in the first place.
> Is there any other way available for doing this? Also which one of the
> above two is more efficient and is a better way to resolve the
> mentioned problem.
Of the two you mentioned, I'd say that unless when a timeout occurs your
plan is to close the socket, the first option is a non-starter, leaving
you only with the second. Of course, as I mentioned, the second option is
not so good either. If you want to have a timeout and still have a socket
that usable after the timeout, you shouldn't be using blocking sockets in
the first place.
If it's okay for the socket to be closed when the timeout happens, then
I'd say any of the solutions would probably work fine, but I'd probably
stick with setting the socket option for the timeout and just make the
blocking calls as you would otherwise. That seems like the simplest
approach, and simple is good.
Pete
The WSAEventSelect and WSAAsyncSelect functions automatically set the
socket to nonblocking mode.
> When I use a blocking socket with send/recv calls, the call will block
> till the operation is completed. Supposing a recv call blocks for a
> long time due to no data being sent from the peer, is there a way to
> make the recv call return?
Don't do that. Blocking sockets are more trouble than they're worth.
If you must do this, you can use 'alarm' prior to the blocking socket
call. But I'd suggest just using non-blocking sockets.
> Currently I know of two options:
>
> 1. Setting the socket options for timeout using SO_RCVTIMEO /
> SO_SNDTIMEO so that the call times out after a specified time if there
> is no data available on the socket.
That's not implemented consistently. Plus, it's simply incorrect
logically. You want the operation to time out, not the connection.
> 2. Use a select call with a timeout before the actual call to recv.
That will work under all known circumstances. But it's not
recommended, since nothing guarantees that it will work. There may be
circumstances you cannot foresee under which it fails to work.
> Is there any other way available for doing this? Also which one of the
> above two is more efficient and is a better way to resolve the
> mentioned problem.
>
> I hope this is the right group to post this message. Any pointers will
> be helpful.
I would just recommend using non-blocking sockets. Keep track of the
last time you heard from each connection, and if that time amount gets
to be too much, you can shutdown the client, send some data to the
client to see if it's still there, or whatever is appropriate.
DS
Thanks a lot for all your replies.
But, I still have a query. I tried writing a simple program using
SO_RCVTIMEO in windows and I let the recv operation have a timeout.
Recv returned by giving -1 and errno was 10060 (TimedOut). After I
tried again sending/receiving some data on the same socket and it
worked fine. The socket didn't go into a closed state.
Will the behaviour become inconsistent after the usage of SO_RCVTIMEO?
What I read from net also says that SO_RCVTIMEO times out the
operation and not the connection. Am I missing something here?
Obviously my understanding of this seems to be incorrect. Can you
please point me to some documentation or link for understanding this
better?
Thanks!
Regards,
Jayaraghavendran.K
> But, I still have a query. I tried writing a simple program using
> SO_RCVTIMEO in windows and I let the recv operation have a timeout.
> Recv returned by giving -1 and errno was 10060 (TimedOut). After I
> tried again sending/receiving some data on the same socket and it
> worked fine. The socket didn't go into a closed state.
> Will the behaviour become inconsistent after the usage of SO_RCVTIMEO?
The documentation says no, but real-world experience says maybe.
Google 'SO_RCVTIMEO' and you will see that the net is littered with
problems.
> What I read from net also says that SO_RCVTIMEO times out the
> operation and not the connection. Am I missing something here?
You're missing the history of disaster and failures with this option.
It's very much liks MSG_PEEK in that regard. It's a poorly thought
out, poorly designed misfeature. It seems to sometimes work and
sometimes not.
> Obviously my understanding of this seems to be incorrect. Can you
> please point me to some documentation or link for understanding this
> better?
I haven't been able to find a good single point of reference for this.
It's just one of those things that experience has shown doesn't work.
Using 'alarm', 'setitimer', or blocking sockets has proven to be
reliable.
DS
> Hi All,
>
> Thanks a lot for all your replies.
>
> But, I still have a query. I tried writing a simple program using
> SO_RCVTIMEO in windows and I let the recv operation have a timeout.
> Recv returned by giving -1 and errno was 10060 (TimedOut). After I
> tried again sending/receiving some data on the same socket and it
> worked fine. The socket didn't go into a closed state.
> Will the behaviour become inconsistent after the usage of SO_RCVTIMEO?
As David says, even in lieu of the documentation saying there's a problem,
there can in fact be. That said, the documentation does in fact warn
against using the socket after a timout. From the SO_RCVTIMEO section of
the setsockopt() page
(http://msdn.microsoft.com/en-us/library/ms740476.aspx):
If a send or receive operation times out on a socket,
the socket state is indeterminate, and should not be
used; TCP sockets in this state have a potential for
data loss, since the operation could be canceled at
the same moment the operation was to be completed.
The timeout does timeout the operation, not the socket. But the socket
should be considered unreliable and no longer usable. If you have a
timeout occur, the only thing left that's safe to do with the socket is
close it.
Pete
> What I read from net also says that SO_RCVTIMEO times out the
> operation and not the connection. Am I missing something here?
> Obviously my understanding of this seems to be incorrect. Can you
> please point me to some documentation or link for understanding this
> better?
Remember, these are supposed to be protocol-independent, so you can't
use anything specific that you know about TCP when thinking about the
semantics of SO_RCVTIMEO.
You are probably thinking, "In TCP, it's easy to time out the
operations. So why not define these options to time out the
operations?"
Well, what about a protocol where one side can only send while the
other is blocked in a receive operation? What about a protocol where a
send function doesn't return until the other end acknowledges it? What
do you do if you timeout after sending the data but before receiving
the acknowledgement?
Sure, since it's possible to time out the operation and not the
connection, a TCP implementation might do that. But the SO_RCVTIMEO
option can't require it, because otherwise some protocols would be
impossible to implement.
You can't assume that every protocol that someone might want to
implement makes it possible to time out a receive operation without
timing out the connection.
DS
Thank you for your detailed replies.
The problem here is that, I need to use blocking sockets only.
So, will it be prudent for me use 'select' call instead of
SO_RCVTIMEO?
Or is there any other solution possible where inspite of the timeout,
I don't want to close the socket neither I want the socket to go into
some indeterminate state. I want to continue using it.
I checked extensively and am unable to find any other way of making a
recv/send operation timeout in case of no data receipt.
Any pointers will be helpful. Thanks again for your help!
Regards,
Jayaraghavendran.K
Humm... For some reason I remember reading a that closing the socket while
it has pending operations can possibly cause a memory leak. Perhaps it only
applies to overlapped i/o, not blocking.
<doing some research>
Ahh, okay; I remember where I heard it and it seems to only apply to pending
AcceptEx:
http://www.microsoft.com/mspress/books/sampchap/5726.aspx#SampleChapter
You can't reliably use 'select' call with blocking sockets. Suppose
the blocking socket call blocks -- it will block forever.
> Or is there any other solution possible where inspite of the timeout,
> I don't want to close the socket neither I want the socket to go into
> some indeterminate state. I want to continue using it.
>
> I checked extensively and am unable to find any other way of making a
> recv/send operation timeout in case of no data receipt.
>
> Any pointers will be helpful. Thanks again for your help!
You are asking, "how can I use blocking sockets but not block?" The
answer is that you can't.
DS