C, socket programmering: sådan Tilsluttes flere klienter til en server ved hjælp af select()

Jeg forsøger at lave en server, der kan være sluttet til flere kunder. Her er min kode så langt:

Klient:

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;
}

Så snart klienten opretter forbindelse til og sender sine første besked, kan serveren kun kører i en uendelig løkke, og spytter ud skrald fra beskeden array. recv synes ikke at modtage noget. Nogen der kan se hvor jeg går galt?

OriginalForfatteren ragnaroh | 2010-11-16

5 svar

  1. 4

    To spørgsmål i din kode:

    • Du skal gøre recv(i, ...) i stedet for recv(clientsock[i], ...)

    • Efter, at du ikke ind, hvis recv() mislykkedes, og derfor printf() udskriver den uinitialiseret buffer message, og derfor skrald i output

    OriginalForfatteren thkala

  2. 1

    Du nødt til at tjekke for at begrænse <= 0 i din læst loop, før du kalder læse.

    OriginalForfatteren user207421

  3. 1

    I while-løkken til serveren, skal du ændre koden til at gøre recv(i) i stedet for recv(clientsocks[i]). Jeg har implementeret denne kode, og det virker med denne ændring.

    OriginalForfatteren Chaitra Suresh

  4. 0

    Jeg erstattet det andet, med nedenfor, og det virker

     } else {
    /*                  int messageLength = 5;
                        char message[messageLength+1];
                        int in, index = 0, limit = messageLength+1;
    
                        memset ( &message[index] , 0, sizeof ( message [index] ) );
    
                        while ((in = recv(i, &message[index], limit, 0)) > 0) {
                            index += in;
                            limit -= in;
                        }
    
                        printf("%d\n", index);
                        printf("%s\n", message);
    */
                        bzero(buf, sizeof(buf));
                        if ((rval = read(i, buf, 1024)) < 0)
                            perror("reading stream message");
                        else if (rval == 0)
                            printf("Ending connection\n");
                        else
                            printf("-->%s\n", buf);
    
                    }
    Du behøver ikke bzero(). Bare tage behørigt hensyn til den værdi, der returneres af recv(), for eksempel i printf("-->%.*s\n", rval, buf);.

    OriginalForfatteren resultsway

  5. 0

    1) Det er en god ide at bruge PF_INET(protokol familie) snarere end

    AF_INET(adresse familie) i Stikket skabelse .

    2) inden for de while(1) loop

    hver gang det er tilrådeligt at gøre din readfds tom ved hjælp FD_ZERO(&readfds).
    i recv () – kald, du skal bruge, at jeg hellere end clientsocks[jeg]
    du er nødt til at kontrollere, vende tilbage værdien af recv er negative(hvilket indikerer fejl i læsning), hvis det er tilfældet, vil du ikke nødt til at udskrive meddelelsen.
    under udskrivning beskeden sørg for, at stdout/server er klar til at skrive noget til det, som du kan gøre det ved hjælp af writefds (3rd argument for at vælge).

    OriginalForfatteren Adarsh97

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *