Re: Could not bind
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
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
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
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
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
| 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