C, socket programming: Connecting multiple clients to server using select()

ragnaroh picture ragnaroh · Nov 17, 2010 · Viewed 38.1k times · Source

I'm trying to make a server that can be connected to by multiple clients. Here's my code so far:

Client:

int main(int argc, char **argv) {

  struct sockaddr_in servaddr;
  int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  if (sock == -1) perror("Socket");

  bzero((void *) &servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(6782);
  servaddr.sin_addr.s_addr = inet_addr(<server_ip_address>);

  if (-1 == connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)))
    perror("Connect");

  while(1) {

    char message[6];
    fgets(message, 6, stdin);

    message[5] = '\0';

    send(sock, message, 6, 0);
  }


  close(sock);
}

Server:

int main(int argc, char **argv) {

  fd_set fds, readfds;
  int i, clientaddrlen;
  int clientsock[2], rc, numsocks = 0, maxsocks = 2;

  int serversock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (serversock == -1) perror("Socket");

  struct sockaddr_in serveraddr, clientaddr;  
  bzero(&serveraddr, sizeof(struct sockaddr_in));
  serveraddr.sin_family = AF_INET;
  serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
  serveraddr.sin_port = htons(6782);

  if (-1 == bind(serversock, (struct sockaddr *)&serveraddr, 
                 sizeof(struct sockaddr_in))) 
    perror("Bind");

  if (-1 == listen(serversock, SOMAXCONN))
    perror("Listen");

  FD_ZERO(&fds);
  FD_SET(serversock, &fds);

  while(1) {

    readfds = fds;
    rc = select(FD_SETSIZE, &readfds, NULL, NULL, NULL);

    if (rc == -1) {
      perror("Select");
      break;
    }

    for (i = 0; i < FD_SETSIZE; i++) {
      if (FD_ISSET(i, &readfds)) {
        if (i == serversock) {
          if (numsocks < maxsocks) {
            clientsock[numsocks] = accept(serversock,
                                      (struct sockaddr *) &clientaddr,
                                      (socklen_t *)&clientaddrlen);
            if (clientsock[numsocks] == -1) perror("Accept");
            FD_SET(clientsock[numsocks], &fds);
            numsocks++;
          } else {
            printf("Ran out of socket space.\n");

          }
        } else {
          int messageLength = 5;
          char message[messageLength+1];
          int in, index = 0, limit = messageLength+1;

          while ((in = recv(clientsock[i], &message[index], limit, 0)) > 0) {
            index += in;
            limit -= in;
          }

          printf("%d\n", index);
          printf("%s\n", message);

        }
      }
    }
  }

  close(serversock);
  return 0;
}

As soon as a client connects and sends its first message, the server just runs in an infinite loop, and spits out garbage from the message array. recv doesn't seem to receive anything. Can anyone see where i go wrong?

Answer

thkala picture thkala · Nov 17, 2010

Two issues in your code:

  • You should do recv(i, ...) instead of recv(clientsock[i], ...)

  • After that you do not check if recv() failed, and therefore printf() prints out the uninitialised buffer message, hence the garbage in the output