Re: Could not bind

2001-09-21 Thread Stephen Montgomery-Smith

Thanks everyone for exellent answers - I learned something from every
single email I received in response.

Thanks, Stephen


 Stephen Montgomery-Smith wrote:
 
  I have written a server program that listens on port 3000.  The program
  works very well except for one feature.  I am asking if that is normal,
  or whether I forgot something.
 
  If I run the program it does fine.  If I then kill the program (after it
  has accepted connections), and then run the program again, the bind
  function fails to work, and I get a message like Could not bind (see
  program below).  If I wait a while, like a minute or two, then the
  program will work again. Is this normal behavior, or did I miss
  something?
 




-- 

Stephen Montgomery-Smith  [EMAIL PROTECTED]
307 Math Science Building [EMAIL PROTECTED]
Department of Mathematics [EMAIL PROTECTED]
University of Missouri-Columbia
Columbia, MO 65211
USA

Phone (573) 882 4540
Fax   (573) 882 1869

http://www.math.missouri.edu/~stephen

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-hackers in the body of the message



Re: Could not bind

2001-09-16 Thread Terry Lambert

Stephen Montgomery-Smith wrote:
 
 I have written a server program that listens on port 3000.  The program
 works very well except for one feature.  I am asking if that is normal,
 or whether I forgot something.
 
 If I run the program it does fine.  If I then kill the program (after it
 has accepted connections), and then run the program again, the bind
 function fails to work, and I get a message like Could not bind (see
 program below).  If I wait a while, like a minute or two, then the
 program will work again. Is this normal behavior, or did I miss
 something?

This is normal.

When a server closes the connection, which will occur in the
resource-track-cleanup case of you killing the server, the
connections effectively undergo a host close.  If the clients
are still around and responsive, these conections will go away
quickly.  If not, then these connections will hand around a
long time.  In addition, in the case of client initiated closes
prior to your temination of the program, the sockets will be in
TIME_WAIT state for 2MSL -- 60 seconds, by default.

So in normal operation, you should expect that you will not be
able to restart the server for at least 60 seconds, and perhaps
more, unless you have unset the keepalive socket option on the
sockets to prevent the FIN_WAIT_2 state.

A common overreaction to improrper state tracking by the programmer,
or improper clean shutdown of a server is to set SO_REUSEADDR
on the listen socket of the server.  THis lets you restart the
server.  But it also lets you start multiple instances of the
server, so if you are doing things like cookie state tracking which
are server instance specific (e.g. for an HTTP server), then you
have shot yourself in the foot, unless this state is shared between
all server instances, and your servers are anonymous work-to-do
engines, rather than being specific-purpose (this is because you
can not control the connections to make them go to one server vs.
another, if both are listening on the same port).

Ideally, you would correct the shutdown so that it was clean,
and correct the socket options, if what you are intending is
to abort the server without sending complete data to the client
(e.g. unsetting SO_LINGER will cause the sending of an RST on
close, avoiding the TIME_WAIT, but potentially leaving the
client hanging until the longer -- 2 hour, by default -- clock
on the client sends a keepalive, and the RST is resent; this is
because RST's are not resent, as they do not get acknowledgement).

As a workaround, you can set SO_REUSEADDR on the socket.  Above,
I labelled this as an overreaction... it is.  For this to work,
you will probably need to make sure your server creates a pid
file in /var/run/servername.pid, and then, before you reopen
the socket, verify via kill(2), using a signal argument of 0,
that the process is in fact dead, before grabbing its port out
from under it for half the inbound connections (see the 2 kill
man page for details on the 0 signal; a 0 return or a -1 return
with errno == EPERM mean the process your are trying to replace
is already running).


 I got the programming style from Richard Steven's book on network
 programming.  The structure of the program is something like this:

[ ... example elided ... ]

That's all fine; the problem is just an incomplete understanding
of the TCP protocol; hopefully the above will fill you in; in the
man time, you may want to get the internals volumes from the
Steven's books series, and read them, as well, since it's often
useful to understand why you are seeing what you are seeing; the
user space volumes are only half the story.

-- Terry

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-hackers in the body of the message



Could not bind

2001-09-15 Thread Stephen Montgomery-Smith

I have written a server program that listens on port 3000.  The program
works very well except for one feature.  I am asking if that is normal,
or whether I forgot something.

If I run the program it does fine.  If I then kill the program (after it
has accepted connections), and then run the program again, the bind
function fails to work, and I get a message like Could not bind (see
program below).  If I wait a while, like a minute or two, then the
program will work again. Is this normal behavior, or did I miss
something?

I got the programming style from Richard Steven's book on network
programming.  The structure of the program is something like this:


typedef struct {
  int connfd;
  struct in_addr addr;
  u_short port;
}
arg_pass_type;

void *process_client(void *arg) {
  int connfd = ((arg_pass_type*)arg)-connfd;
  struct in_addr addr = ((arg_pass_type*)arg)-addr;
  u_short port = ((arg_pass_type*)arg)-port;

  free(arg);
  pthread_detach(pthread_self());
  do_lots_of_stuff();

}

int main () {
  int listenfd;
  struct sockaddr_in servaddr;
  socklen_t slen;
  pthread_t tid;
  arg_pass_type *arg;

  listenfd=socket(AF_INET,SOCK_STREAM,0);
  bzero(servaddr,sizeof(servaddr));
  servaddr.sin_family=AF_INET;
  servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
  servaddr.sin_port=htons(3000);
  if (bind(listenfd,(struct sockaddr*)servaddr,sizeof(servaddr))  0)
  {
fprintf(stderr,Could not bind\n);
exit(1);
  }
  listen(listenfd,6);

  while (1)
  {
slen=sizeof(servaddr);
arg = malloc(sizeof(arg_pass_type));
arg-connfd = accept(listenfd,(struct sockaddr*)servaddr,slen);
arg-addr = servaddr.sin_addr;
arg-port = servaddr.sin_port;
pthread_create(tid,NULL,process_client,(void*) arg);
  }
  exit(0);
}

-- 
Stephen Montgomery-Smith
[EMAIL PROTECTED]
http://www.math.missouri.edu/~stephen

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-hackers in the body of the message



Re: Could not bind

2001-09-15 Thread Matthew Jacob


You should always use perror or strerror if a system call fails so you know
*why* it fails. Then you can cross-references with the man(2) and man(3) pages
to figure out what's up.


On Sat, 15 Sep 2001, Stephen Montgomery-Smith wrote:

 I have written a server program that listens on port 3000.  The program
 works very well except for one feature.  I am asking if that is normal,
 or whether I forgot something.
 
 If I run the program it does fine.  If I then kill the program (after it
 has accepted connections), and then run the program again, the bind
 function fails to work, and I get a message like Could not bind (see
 program below).  If I wait a while, like a minute or two, then the
 program will work again. Is this normal behavior, or did I miss
 something?
 
 I got the programming style from Richard Steven's book on network
 programming.  The structure of the program is something like this:
 
 
 typedef struct {
   int connfd;
   struct in_addr addr;
   u_short port;
 }
 arg_pass_type;
 
 void *process_client(void *arg) {
   int connfd = ((arg_pass_type*)arg)-connfd;
   struct in_addr addr = ((arg_pass_type*)arg)-addr;
   u_short port = ((arg_pass_type*)arg)-port;
 
   free(arg);
   pthread_detach(pthread_self());
   do_lots_of_stuff();
 
 }
 
 int main () {
   int listenfd;
   struct sockaddr_in servaddr;
   socklen_t slen;
   pthread_t tid;
   arg_pass_type *arg;
 
   listenfd=socket(AF_INET,SOCK_STREAM,0);
   bzero(servaddr,sizeof(servaddr));
   servaddr.sin_family=AF_INET;
   servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
   servaddr.sin_port=htons(3000);
   if (bind(listenfd,(struct sockaddr*)servaddr,sizeof(servaddr))  0)
   {
 fprintf(stderr,Could not bind\n);
 exit(1);
   }
   listen(listenfd,6);
 
   while (1)
   {
 slen=sizeof(servaddr);
 arg = malloc(sizeof(arg_pass_type));
 arg-connfd = accept(listenfd,(struct sockaddr*)servaddr,slen);
 arg-addr = servaddr.sin_addr;
 arg-port = servaddr.sin_port;
 pthread_create(tid,NULL,process_client,(void*) arg);
   }
   exit(0);
 }
 
 -- 
 Stephen Montgomery-Smith
 [EMAIL PROTECTED]
 http://www.math.missouri.edu/~stephen
 
 To Unsubscribe: send mail to [EMAIL PROTECTED]
 with unsubscribe freebsd-hackers in the body of the message
 


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-hackers in the body of the message



Re: Could not bind

2001-09-15 Thread Ben Smithurst

Stephen Montgomery-Smith wrote:

   listenfd=socket(AF_INET,SOCK_STREAM,0);
   bzero(servaddr,sizeof(servaddr));
   servaddr.sin_family=AF_INET;
   servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
   servaddr.sin_port=htons(3000);
   if (bind(listenfd,(struct sockaddr*)servaddr,sizeof(servaddr))  0)

You probably need to set the SO_REUSEADDR socket option; Stevens talks
about this eventually, maybe you haven't read that far.  Basically you
need something like

int foo = 1;

and then call

setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, foo, sizeof foo);

between the socket() and listen() calls.  Check setsockopt(2) and
Stevens for more information (and to make sure I got the arguments and
stuff right!)

-- 
Ben Smithurst / [EMAIL PROTECTED] FreeBSD: The Power To Serve
http://www.FreeBSD.org/

 PGP signature


Re: Could not bind

2001-09-15 Thread Dan Moschuk


| I have written a server program that listens on port 3000.  The program
| works very well except for one feature.  I am asking if that is normal,
| or whether I forgot something.
| 
| If I run the program it does fine.  If I then kill the program (after it
| has accepted connections), and then run the program again, the bind
| function fails to work, and I get a message like Could not bind (see
| program below).  If I wait a while, like a minute or two, then the
| program will work again. Is this normal behavior, or did I miss
| something?

[ snip ]

This is normal behavior.  bind() will fail if there are still sockets in 
the TIME_WAIT (and other) states.

To get around this, you want to use set the SO_REUSEPORT option using
setsockopt().

-Dan

-- 
Build a man a fire, and he'll be warm for a day.
Set a man on fire, and he'll be warm for the rest of his life.


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-hackers in the body of the message