2

Here is a Server implementation with select ()`, and a simple client. It is not the main app, but an example, which may not run. What matters is that infinite loop from server.

The problem appears here: the client sends a (correct) message, receives an (correct) answer from server, and then, when he sends another message, it receives Error: write (): Bad file descriptor.

I checked back in server and he didn't close it. I suspect that the problem either in select () or in server architecture.

EDIT: I test my app on 127.0.0.1, if relevant.

Server

        #include <sys/types.h>
        #include <sys/socket.h>
        #include <sys/time.h>
        #include <netinet/in.h>
        #include <unistd.h>
        #include <errno.h>
        #include <stdio.h>
        #include <arpa/inet.h>
        #include <string.h>

        #define PORT 2728

        extern int errno;       

        /* converting client address int char*  */
        char * conv_addr (struct sockaddr_in address)
        {
          static char str[25];
          char port[7];

          strcpy (str, inet_ntoa (address.sin_addr));   

          bzero (port, 7);
          sprintf (port, ":%d", ntohs (address.sin_port));  
          strcat (str, port);
          return (str);
        }


        int main ()
        {
          struct sockaddr_in server;    
          struct sockaddr_in from;
          fd_set readfds;   //clients which are ready to write  
          fd_set actfds;    //active clients    
          struct timeval tv;        
          int sd, client;       
          int optval=1;             
          int fd;           
          int nfds;      //max number of descriptors        
          int len;          


          if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
            {
              perror ("[server] Error:socket().\n");
              return errno;
            }

          /*SO_REUSEADDR  option*/ 
          setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,&optval,sizeof(optval));


          bzero (&server, sizeof (server));


          server.sin_family = AF_INET;
          server.sin_addr.s_addr = htonl (INADDR_ANY);
          server.sin_port = htons (PORT);


          if (bind (sd, (struct sockaddr *) &server, sizeof (struct sockaddr)) == -1)
            {
              perror ("[server] Error:bind().\n");
              return errno;
            }


          if (listen (sd, 5) == -1)
            {
              perror ("[server] Error:listen().\n");
              return errno;
            }


          FD_ZERO (&actfds);        
          FD_SET (sd, &actfds);     

          tv.tv_sec = 1;        
          tv.tv_usec = 0;


          nfds = sd;

          printf ("[server] Waiting at port %d...\n", PORT);
          fflush (stdout);

          /* serving clients... */
          while (1)
            {

              bcopy ((char *) &actfds, (char *) &readfds, sizeof (readfds));


              if (select (nfds+1, &readfds, NULL, NULL, &tv) < 0)
            {
              perror ("[server] Error:select().\n");
              return errno;
            }


              if (FD_ISSET (sd, &readfds))
            {
              /* preparing client structure */
              len = sizeof (from);
              bzero (&from, sizeof (from));


              client = accept (sd, (struct sockaddr *) &from, &len);


              if (client < 0)
                {
                  perror ("[server] Error:accept()\n");
                  continue;
                }

                  if (nfds < client) /* adjusting max value */
                    nfds = client;


              FD_SET (client, &actfds);

              printf("[server] Client with %d descriptor and %s address connected.\n",client, conv_addr (from));
              fflush (stdout);
            }

              /* checking if any client is ready so 'speak' */
              for (fd = 0; fd <= nfds; fd++)    
            {

              if (fd != sd && FD_ISSET (fd, &readfds))
                {   

                       //receive message from client
                       //do something 
                       //sent back result

                }
            }
                            /* for */
            }               /* while */
        }               /* main */

Client

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

    extern int errno;


    int port;

    int main (int argc, char *argv[])
    {
      int sd;           
      struct sockaddr_in server; 
      char msg[100];    

      if (argc != 3)
        {
          printf ("[client] Sintax: %s <server_address> <port>\n", argv[0]);
          return -1;
        }

      port = atoi (argv[2]);

      if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
        {
          perror ("[client] Error:socket().\n");
          return errno;
        }


      server.sin_family = AF_INET;
      server.sin_addr.s_addr = inet_addr(argv[1]);
      server.sin_port = htons (port);


      if (connect (sd, (struct sockaddr *) &server,sizeof (struct sockaddr)) == -1)
        {
          perror ("[client]Error: connect().\n");
          return errno;
        }


    while(1)/*meaning untill user doesn't close the client*/)
     {

        //here are the functions used to communicate with server. Same in server.

      if (write (sd, msg, 100) <= 0)
        {
          perror ("[client]Error:write().\n");
          return errno;
        }


      if (read (sd, msg, 100) < 0)
        {
          perror ("[client]Error:read().\n");
          return errno;
        }

     }//while

      close (sd);

  }//main

Source

Daniel
  • 39
  • 5

2 Answers2

1
while(/*user doesn't close client*/)
 {
    //here are the functions used to communicate with server. Same in server.

  if (write (sd, msg, 100) <= 0)
    {
      perror ("[client]Error:write().\n");
      return errno;
    }
  if (read (sd, msg, 100) < 0)
    {
      perror ("[client]Error:read().\n");
      return errno;
    }
 }
  close (

If this loop fails in the second write with EBADF, clearly this isn't the real code, and clearly the close is one line higher, inside the loop, as its indentation suggests.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Yes, it is not the real code, and about your observation on close(socket): Using close() in loop will close the connection betwen client and server after first send-recieve...or my intention is to keep it open untill client quits, not close() - connect on every iteration. – Daniel Jan 04 '15 at 20:09
  • I don't know what this comment means, unless you're just agreeing with me. – user207421 Jan 05 '15 at 08:19
-1

the code for both the server and the client seem to be missing setting the 'SO_KEEPALIVE' option. suggest using something like:

int keepAlive = 1;


if( 0 > setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE,
               &keepAlive, (socklen_t)sizeof(keepAlive)) )
{ // then, setsockopt failed
    // process error
}

the current code creates a socket via:

if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
{ // then socket failed
    // process error
}

suggest using:

if ((sd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{ // then socket failed
    // process error
}
user3629249
  • 16,402
  • 1
  • 16
  • 17