How do you close a socket when a client doesn't close it ?

:unamused:
I found that if you your client crashed and doesn’t close the socket then on the server side u can’t close the socket and u have to reboot or restart TCPIP.

Here is tut7.c

         #include <sys/types.h>
          #include <sys/socket.h>
          #include <sys/time.h>
          #include <netinet/in.h>
          #include <sys/select.h>
          #include <netdb.h>
          #include <stdio.h>
          #include <string.h>
          #include <unistd.h>
          #include <stdlib.h>

          #define TRUE 1

          /*
           * This program uses  select() to check that someone is trying to connect
           * before calling accept().
           */

          main()
          {
                  int sock, length;
                  struct sockaddr_in server;
                  int msgsock;
                  char buf[1024];
                  int rval;
                  fd_set ready;
                  struct timeval to;

                  /* Create socket */
                  sock = socket(AF_INET, SOCK_STREAM, 0);
                  if (sock < 0) {
                          perror("opening stream socket");
                          exit(1);
                  }
                  /* Name socket using wildcards */
                  server.sin_family = AF_INET;
                  server.sin_addr.s_addr = INADDR_ANY;
                  server.sin_port = 0;
                  if (bind(sock, (struct sockaddr *)&server, sizeof(server))) {
                          perror("binding stream socket");
                          exit(1);
                  }
                  /* Find out assigned port number and print it out */
                  length = sizeof(server);
                  if (getsockname(sock, (struct sockaddr *)&server, &length)) {
                          perror("getting socket name");
                          exit(1);
                  }
                  printf("Socket has port #%d\n", ntohs(server.sin_port));

                  /* Start accepting connections */
                  listen(sock, 5);
                  do {
                          FD_ZERO(&ready);
                          FD_SET(sock, &ready);
                          to.tv_sec = 5;
                          if (select(sock + 1, &ready, 0, 0, &to) < 0) {
                                  perror("select");
                                  return EXIT_FAILURE;
                          }
                          if (FD_ISSET(sock, &ready)) {
                                  msgsock =  accept(sock, (struct  sockaddr *)0, (int *)0);
                                  if (msgsock == -1) {
                                          perror("accept");
					  return EXIT_FAILURE;
                                  } else do {
                                          memset(buf, 0, sizeof(buf));
                                          if  ((rval  =  read(msgsock, buf, sizeof(buf))) < 0)
                                                  perror("reading    stream message");
                                          else if (rval == 0)
                                                  printf("Ending connection\n");
                                          else
                                                  printf("-->%s\n", buf);
                                  } while (rval > 0);
                                  close(msgsock);
                          } else
                                  printf("Do something else\n");
                  } while (TRUE);
          }

If you unplug the network cable from your client or if you shutdown without to close his socket then you are screwed and u have to reboot your server.

Any idea ?

I dont think you have to reboot or restart TCPIP.

Of course you can close the socket, the problem is to detect that the client has disconnected. I think you would have to implement a application timeout on the read() and check for last time it has actually read something and close when the time exceeded a threshold (may be 1 second for a high priority control or 5 minutes for a low priority file transfer, depends on purpose of the connection…)

You can set timeout on read()/recv() calls with a setsockopt(SO_RCVTIMEO) or use a select() loop to timeout and to detect when it is safe to call read() which will not block

These examples do not cover all errors which can arise

Malek,
If your client failed to disconnected properly then this


close (msgsock);

will not work and you have to reset TCPIP or reboot.

I found some info

How come I get “address already in use” from bind()?
developerweb.net/sock-faq/detail.php?id=40

Please explain the TIME_WAIT state.
developerweb.net/sock-faq/detail.php?id=13

How do I properly close a socket?
developerweb.net/sock-faq/detail.php?id=31

Ok I did some testing and this is what I found so far.

If you close your program then you will have to wait for the timer to expired before to bind the same port again.So reboot or restart TCPIP is not really necessary. But you have to wait something like 1-2 min before to restart your application.

Now let me explain what is my problem :

  My goal is to write a server that will listen on one port and create an array of socket. I would like to be able to serve up to 100 client. Those client wil be all serial - ethernet converter.

Now if a client get unplug or reset I’m not receiving any signal from them.

The Select,Read,FD_ISSET function don’t give me any signal at all.


if (msgsock >0)
     {	
      FD_ZERO(&ready);
      FD_SET(msgsock, &ready);
      to.tv_sec = 0;
      to.tv_usec = 30;

      if (n=select(msgsock + 1, &ready, 0, 0, &to) < 0) 
           {
            perror("select");
            return;
            }
      else printf("N -> %d\n",n);

      if (n=FD_ISSET(msgsock, &ready))
           {
            printf("N ->%d\n",n);
            memset(buf, 0, sizeof(buf));             
            rval  = read(msgsock, buf,  1024);

            if (rval < 0) printf ("Error reading stream message");
            else if (rval > 0) printf ("Data-->%s\n", buf);
            else 
               {
                printf("Connection terminated ...\n");
                close(msgsock);
                msgsock=0;
                }
            }
        else printf("N ->%d\n",n);
        }

Anyone know how to solve this ?

This is very basic TCP/IP stuff, you should get a book about it. If you don’t understand exactly what is going on, then you’ll never be able to write solid code.

Don’t write code that works by chance, write code that works by design ;-)