Advertisement

Socket Timeout

Started by July 23, 2002 04:38 AM
3 comments, last by encom 22 years, 3 months ago
Hi, I dont know how to modify the connection/send/receive timeout/retries ? It will be very usefull for my server. I know the command setsockopt but i dont understand the way to use it ! Does anybody can explain it to me ? thanx a lot
quote: Original post by encom
Hi,

I dont know how to modify the connection/send/receive timeout/retries ? It will be very usefull for my server.
I know the command setsockopt but i dont understand the way to use it !

Does anybody can explain it to me ?


thanx a lot


It''s a low level call, so it would help to know your system.

Anyway, in a nutshell:

Setting timeout values at the socket level through setsockopt() isn''t supported on some *nix (Linux, SunOS 4+, etc) while it is on some others (*BSD, maybe others). On systems that don''t support this, you''ve got to use alarm() or setitimer() and have your application handle the signal sent by the timers (SIGALRM) with signal().

This would set the socket receive timeout at 5 seconds (on systems that support it):

struct timeval tv;tv.tv_sec = 5;tv.tv_usec = 0;setsockopt(mysocket, SO_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)); 


To get the value:

struct timeval tv;socketlen_t s;memset(&tv, 0, sizeof(struct timeval));s = sizeof(struct timeval);getsockopt(mysocket, SO_SOCKET, SO_RCVTIMEO, &tv, &s); 



Doing so at the protocol level is the same, just replace SO_SOCKET with the appropriate protocol name:

struct timeval tv;struct protoent *proto;tv.tv_sec = 5;tv.tv_usec = 0;proto = getprotobyname("tcp";setsockopt(mysocket, proto->p_proto, SO_RCVTIMEO, &tv, s); 



Search your man pages for the various options and their parameters (getsockopt(2) and socket(7) on GNU/Linux, getsockopt(2) on *BSD and SunOS, no idea about the others ).

I haven''t done this in a long while, so please correct me if I''m wrong.

Hope this helps.
Advertisement
ok, thank you....
but u say it wont works under linux, so how can i do it with signal ?
Everything is in the man pages I mentioned in my previous post. Anyway, here is an example with setitimer and signals:


  #include <stdio.h>#include <stdlib.h>#include <signal.h>#include <sys/time.h>/* this is a callback that will be called   when the timer sends a SIGALRM */void sig_handler(int signum) {  static size_t count = 0;  printf("received SIGALRM %d\n", count);  /* exit after a while */  if (++count == 10) {    exit(0);  }}int main(int argc, char *argv[]) {  /*    a struct itimerval is:    struct itimerval {      struct timeval it_value;      struct timeval it_interval;    };  */  struct itimerval timer;  /*    set the timer to start 1 second after setitimer() is called.  */  timer.it_value.tv_sec = 1;  timer.it_value.tv_usec = 0;  /*    and to restart every second  */  timer.it_interval = timer.it_value;  /*    see setitimer(2) for informations about other    kind of timers and the signals they generate  */  setitimer(ITIMER_REAL, &timer, NULL);  /*    this tells the system to call our callback when    the process receives a SIGALRM signal (generated    by the timer).  */  signal(SIGALRM, sig_handler);  /*    loop forever. The callback will exit the program.  */  while(1);  /*    never reached  */  return 0;}  


I used setitimer() and not alarm() because it''s easier to set a restart interval. However, setitimer() is not POSIX, alarm() is. I don''t know of any "clean" way to set a restart value for alarm(), other than generating another timer in the signal handler like this:


  #include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>void sig_handler(int signum) {  static size_t count = 0;  printf("received SIGALRM %d\n", count);  if (++count == 10) {    exit(0);  }  /*    set a new timer that will call this function back in    1 second  */  alarm(1);}int main(int argc, char *argv[]) {  /*    connect the signal handler  */  signal(SIGALARM, sig_handler);  /*    tell the system to send a SIGALRM signal in 1 second  */  alarm(1);  while(1);  return 0;}  


Back to your socket problem, you''d set a signal callback and a timer. If you don''t receive the data from the socket in that interval, a SIGALRM will be sent and your callback will be called. Do whatever has to be done about it in your callback. If you do receive the data, then cancel the timer. I''ll let you guess how to do this (check the man pages). Note that you should avoid mixing calls to setitimer() and alarm(). Note also that, while setitimer() will accept intervals of 1 millisecond, it is limited by the precision of the system.

Of course this is only for socket level timeouts. Linux can handle protocol level timeouts without any problem.

Again, I haven''t done anything like this in a long while, so everything I''ve said should be taken with a grain of salt.

Hope this helps.
Ooooooooooooooooooookk !

Nice, thanks a lot for the code !

This topic is closed to new replies.

Advertisement