tags:

views:

107

answers:

2

Hey I was writing a udp client server in which a client waits for packets from server.But I want to limit this wait for certain time.After client don't get response for a certain moment in raise an alarm,basically it comes out and start taking remedy steps.So what are the possible solution for it.I think writing a wrapper around recv will work but how exactly this has to be done,I mean how will make recv raise alarm for you after that time limit.

Any Help in this regard will be appreciated.

Thanks!

+6  A: 

If you want to do socket communications with timeouts, then select is the way to go.

You basically set up arrays of file descriptors for various events such as read-ready or write-able, then call select with a timeout. If one of the events is valid, you will be notified and you can perform your actions.

If none of the events occurs before the timeout, you'll still be notified and can take whatever remedial action you see fit.

See here for the gory details, expanded on below.

Alternatively, you can use setsockopt with the SO_RCVTIMEO:

struct timeval tv;
tv.tv_sec = 5;
tv.tv_used = 0;
setsockopt (socket_id, SOL_SOCKET, SO_RCVTIMEO,
    &tv, sizeof(struct timeval));

For details on select, you use the FD_ZERO and FD_SET macros to construct a set of file descriptors (fdsets) of interest to you. You can have three sets, one indicating whether one or more fds has data to read, one indicating whether one or more is ready for writing to, and one indicating errors. You may not necessarily have all three, it depends on what your code is doing.

Once you've set up the fdsets, you pass them, along with the number of fds and a timeout, to select which weaves its magic and returns to you. Before you do this, make a copy (FD_COPY) of the fdsets for later recovery.

On return, there's either been an error, timeout or an event pertaining to one of the fds of interest. In that latter case, the fdsets have been modified to only have the fds set for those with an event and you can use FD_ISSET to detect which ones.

Then, once you've handled all the events, use FD_COPY to restore the original fdsets (they were modified by select, remember) and call select again. Continue for as long as you need to.

Keep in mind that an error return from select is not necessarily fatal. You can get (in errno) EAGAIN for a temporary resource shortage or EINTR if a signal was handled. For that second case, you can just re-enter the select call. For the first, I'd implement a retry loop in case it was just a temporary thing.

paxdiablo
thansk for the reply.
mawia
Hi!Is there any way to know using select,on which of the file descriptor action has taken place?I mean if we are passing a set file descriptor we obviously will need some info on return of select regarding which exactly is the file descriptor where action has taken place as it will help in taking further action accordingly.Thanks!
mawia
Yes, the descriptor sets are _modified_ so that only the bits that have an event are set. `select` will return -1 on error (check errno), 0 on timeout and number of events otherwise. If you get a positive ineteger, you then use FD_ISSET to check each file descriptor in the set. Just make sure you re-init the fd set before calling select again.
paxdiablo
Load of thanks again!!
mawia
+1  A: 

You can use select(...) with a non-zero timeout as the last argument. That's the most portable way.

You could also use signals, but that's not portable, and even on systems that have it, it may not work like you expect by default. (The recv/select/whatever might get restarted once the signal handler's done, defeating the whole purpose.)

cHao
Thanks for the reply.
mawia