Search code examples
cmultithreadingunix-socket

Unix socket Multiple client group chat with client name in c


So far everything have been working perfectly. Just the problem I've been having is that I can't think of a way of assigning or i would say giving names to the clients who are connect to the server so that other clients who know is wrote a message

server:

while (1) {
    FD_ZERO(&read_set);
    //FD_ZERO(&write_set);

    FD_SET(fd, &read_set);
    //FD_SET(fd, &write_set);

    for (i = 0; i < num_clients; i++) { //at first this part will not excute
        FD_SET(clients[i], &read_set);
    }

    select(fd + num_clients + 1, &read_set, NULL, NULL, NULL);


    if (FD_ISSET(fd, &read_set)) {
        if ((clients[num_clients++] = accept(fd, NULL, NULL)) == -1) {
            perror("accept error");
            continue;
        }
        printf("we got a connection!\n");
    }


    for (i = 0; i < num_clients; i++) {

        if (FD_ISSET(clients[i], &read_set)) {
            msg = read(clients[i], buf, sizeof(buf));
            if (msg > 0) {
                int savedclnt = clients[i];
                printf("client %d says: %s\n", i, buf);

                for (int p = 0; p<num_clients; p++)
                {
                    if (clients[p] != savedclnt) {
                        //write("from %d",clients[p]);
                        //char msg2 = strcat(clients[i],msg);
                        write(clients[p], buf, msg);
                    }

                }
            }
        }
    }
}

Solution

  • For what you're doing, you don't really need threads. From personal experience, a single threaded server would do the job just fine. Instead of having the main body wrap around a call to accept() you should use select() to see which file descriptors have input, something along the lines of...

    fd_set readfds;
    struct timeval timeout;
    unsigned int num_clients;
    unsigned int clients[100];
    while(1)
      {
      FD_ZERO(&readfds);
      FD_SET(sock, &readfds);
      for(i=0; i<num_clients; i++)
        {
        FD_SET(clients[i],&readfds);
        }
      timeout.tv_sec=1;
      timeout.tv_usec=0;
      select(max_fds, &readfds, NULL, NULL, &timeout);
      if(FD_ISSET(sock,&readfds))
        {
        clients[num_clients++] = accept(sock,(struct sockaddr *)&server,&size);
        }
      for(i=0;i<num_clients;i++)
        {
        if(FD_ISSET(clients[i],&readfds))
          {
          int err=read(clients[i],buf,1000);
          if(err>0)
            {
            for(p=0;p<num_clients;p++)
              {
              write(clients[i],buf,err);
              }
            }
          }
        }
      }
    

    That code is just an example and needs error checking to see if a client has disconnected, a way of updating the list of clients and seeing if a client is ready to receive data. But hopefully it gives you the basic idea of where to go?