Sorry if this off-topic post bothers anyone, but I hate to see folks worrying unnecessarily. <offtopic> On 2001-07-27 00:59:12 -0700, David Schwartz wrote: > > > IIRC, close() never blocks. Unlike open(), connect(), and so on, > > there is on special handling for close() when O_NDELAY/O_NONBLOCK is > > set. Scary warnings in the close() man page aside, close() is > > probably the most benign of all I/O calls. > > Since close is the last system call you normally use to access a > socket, it is the underlying network protocol implementation's last > chance to tell you if you have succeeded or failed. As a result, there > are many circumstances under which the 'close' system call will block > until the underlying network protocol can receive acknowledgements for > all outstanding buffered data and shutdown the underlying connection. > > It is generally considered good practice to use the 'shutdown' system > call to shutdown the underlying network connection under program > control. The 'close' system call should be used to deallocate the file > descriptor. This is an interesting theory, but in practice close() on a socket (at least, on a SOCK_STREAM) does not wait for for the session to breakdown, unless you have requested it by setting the linger socket option. I've been programming Unix TCP networks for a while now (8 years or so), and this is simply a non-issue. But don't take my word for it - you can try the attached program. It connects to the specified port, sleeps, then sends some data and calls close(). What I did was connect to a local web server, pull my network cable, and watch it complete. *No errors were reported by any system calls, even with linger enabled.* The close() did delay 10 seconds (as requested by the linger parameter), but then happily returned "no error". If you either remove the write() or the setsockopt(), then it will always return immediately. Now, I ran this on a Linux system (it's the box on my desk, so testing is easy), so the semantics *might* vary on other platforms. But I doubt it. Again I say unto you, just close() those sockets! ;) </offtopic> Shane
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <errno.h> int main(int argc, char *argv[]) { struct hostent *h; struct sockaddr_in addr; int fd; struct linger linger; /* check arguments (a little) */ if (argc != 4) { fprintf(stderr, "Syntax: %s host port timeout\n"); return 1; } /* set up server address structure */ memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; if (inet_aton(argv[1], &addr.sin_addr) == 0) { h = gethostbyname(argv[1]); if (h == NULL) { fprintf(stderr, "Unable to get address for \"%s\"\n", argv[1]); return 1; } memcpy(&addr.sin_addr, h->h_addr, sizeof(struct in_addr)); } addr.sin_port = htons(atoi(argv[2])); /* connect to server */ setbuf(stdout, NULL); printf("Connecting to server..."); fd = socket(PF_INET, SOCK_STREAM, 0); if (fd == -1) { fprintf(stderr, "Error creating socket; %d\n", errno); return 1; } if (connect(fd, &addr, sizeof(struct sockaddr_in)) != 0) { fprintf(stderr, "Error connecting; %d\n", errno); return 1; } printf("connected\n"); /* to sleep, parchance to dream... */ printf("Sleeping (disconnect from the network now)..."); sleep(atoi(argv[3])); printf("done\n"); linger.l_onoff = 1; linger.l_linger = 10; if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger, sizeof(struct linger))) { printf("Error %d setting linger value\n", errno); return 1; } if (write(fd, "HEAD / HTTP/1.0\r\n\r\n", 19) != 19) { printf("Didn't write 19 bytes!\n"); } /* now see what happens when we close */ printf("Closing..."); if (close(fd) != 0) { printf("got error %d..."); } printf("done\n"); /* that's it */ return 0; }