Lockness  | Bonjour tout le monde,
   Je suis en train de coder une application client/serveur se basant sur l'appel système select(). Le problème est que le FD_ISSET() (macro détectant qu'un descripteur de fichiers a été utilisé) est vrai, même si le client n'a rien envoyé !
   Note importante : vous trouverez dans la première réponse à ce message juste les parties du code "intéressantes". Dans ce message, j'ai volontairement mis l'intégralité (enfin, c'est pas non plus monstreux !) des deux codes source (client/serveur).
   Voici le code du serveur :
  Code :
 - #include <stdio.h>
 - #include <stdlib.h>
 - #include <string.h>
 - #include <unistd.h>
 - #include <netdb.h>
 - #include <errno.h>
 - #include <sys/socket.h>
 - #include <sys/types.h>
 - #include <sys/time.h>
 - #include <sys/types.h>
 - #include <sys/select.h>
 - #include <netinet/in.h>
 - #include <arpa/inet.h>
 - #define MAX_PENDING_CONNECT (5U)
 - #define PORT (5000U)
 - #define BUFSIZE (1024)
 - /****************************************************************************
 -  * Macro that allow to save and load the descriptors sets. Indeed, when  
 -  * select is called, it removed all descriptors that have not been modified
 -  * since last call. So, we must have an "history" of the initial set and we
 -  * must load it before each select call in order to consider all  
 -  * descriptors.
 -  ****************************************************************************/
 - #define SAVE_SETS                                                 \
 - {                                                                 \
 -    memcpy(&fds_read_copy, &fds_read, sizeof(fds_read));           \
 - }
 - #define LOAD_SETS                                                 \
 - {                                                                 \
 -    memcpy(&fds_read, &fds_read_copy, sizeof(fds_read_copy));      \
 - }
 - /****************************************************************************
 -  *
 -  * Description : Create a socket, disable its TIME_WAIT option, bind the
 -  * port and listen for connections.
 -  *
 -  * Return
 -  *    - '-1' if the creation failed.
 -  *    - the new file descriptor if the creation succeed.
 -  *
 -  ****************************************************************************/
 - int create_socket(unsigned int port, unsigned int max_pending_connections)
 - {
 -    struct sockaddr_in server_info;     /* Information of the server */
 -    int server_fd;                      /* The file descriptor that will be
 -                                           returned */
 -    int flag;                           /* Flag for the setsockopt func. */
 -    /* Note : htons() is used to convert the port value in the Network Byte  
 -     * Order (NBO). This order is the one used in the TCP/IP packets. */
 -    server_info.sin_family = AF_INET;    /* We treats with IPv4 address */
 -    server_info.sin_port = htons(port);
 -    server_info.sin_addr.s_addr = INADDR_ANY;   /* My IP address :) */
 -    memset(&(server_info.sin_zero), '\0', (size_t)8);
 -    /* Creation of the socket */
 -    if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
 -       return -1;
 -    /* Disable TIME_WAIT */
 -    flag=1;
 -    if(setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) == -1
 - )
 -       fprintf(stderr, "Error while using setsockopt()\n" );
 -    /* Binding the port */
 -    if(bind(server_fd, (struct sockaddr*)&server_info, sizeof(struct sockaddr)) =
 - = -1)
 -       return -1;
 -    /* Listenning connections */
 -    if(listen(server_fd, max_pending_connections) == -1)
 -       return -1;
 -    return (server_fd);
 - }
 - int main()
 - {
 -    fd_set fds_read;              /* Set of file descriptors for reading */
 -    fd_set fds_read_copy;         /* Copy of fds_read not to lose info */
 -    fd_set fds_write_copy;        /* Copy of fds_write not to lose info */
 -    /* List of the file descriptors of each client. The file descriptor
 -     * list_file_descriptors[0] is this of the server. */
 -    int server_fd, new_fd, sin_size, nb_bytes;
 -    int max_fd;
 -    char buffer[BUFSIZE];
 -    struct sockaddr_in client_info;  /* Store the client information */
 -    FD_ZERO(&fds_read);
 -    FD_ZERO(&fds_read_copy);
 -    if((server_fd = create_socket(PORT, MAX_PENDING_CONNECT)) == -1)
 -    {
 -       fprintf(stderr, "Error while creating the socket.\n" );
 -       return (EXIT_FAILURE);
 -    }
 -    FD_SET(server_fd, &fds_read);
 -    SAVE_SETS;
 -    max_fd = server_fd;
 -    while(1)
 -    {
 -       LOAD_SETS;
 -       if(select(max_fd + 1, &fds_read, NULL, NULL, NULL)  == -1)
 -          fprintf(stderr, "select error !\n" );
 -       /* Après un select, les "sets" peuvent être modifié. */
 -       if(FD_ISSET(server_fd, &fds_read))
 -       {
 -          /* Accepting connections :) */
 -          printf("Un client s'est connecté, je l'ajoute dans le set\n" );
 -          sin_size = sizeof(struct sockaddr_in);
 -          if((new_fd = accept(server_fd, (struct sockaddr*)&client_info, &sin_siz
 - e)) == -1)
 -             fprintf(stderr, "Error while accepting connection...\n" );
 -          if(new_fd > max_fd)
 -             max_fd = new_fd;
 -          FD_SET(new_fd, &fds_read);
 -          SAVE_SETS;
 -       }
 -       if(FD_ISSET(new_fd, &fds_read))
 -       {
 -          if ((nb_bytes = recv(new_fd, buffer, 50, 0)) == -1)
 -          {
 -             fprintf(stderr, "Probleme avec la fonction recv()\n" );
 -             exit(EXIT_FAILURE);
 -          }
 -          else
 -             printf("." );
 -       }
 -    }
 -    printf("JE QUITTE\n" );
 -    return EXIT_SUCCESS;
 - }
 
  |  
 
   Vous remarquez donc que dès que le serveur reçoit un message du client, il affiche un point ("." ). Or, avec le client ci-dessous (qui n'envoie que deux messages), le serveur affiche une infinité de points !
   Le code du client :
  Code :
 - #include <stdio.h>
 - #include <stdlib.h>
 - #include <string.h>
 - #include <sys/socket.h>
 - #include <sys/types.h>
 - #include <netinet/in.h>
 - #include <arpa/inet.h>
 - #include <netdb.h>
 - #include <errno.h>
 - #include <unistd.h>
 - #define MAX_PENDING_CONNECT (5)
 - #define PORT (5000)
 - #define BUFSIZE (1024)
 - int main(int argc, char **argv)
 - {
 -    struct sockaddr_in server_info;
 -    struct hostent *hostinfo;
 -    int fd, nb_bytes;
 -    const char msg[] = "CS 'lockness";
 -    char buffer[BUFSIZE];
 -    if(argc < 2)
 -    {
 -       fprintf(stderr, "Hostname or IP in argument please !\n" );
 -       return (EXIT_FAILURE);
 -    }
 -    /*************************
 -     * CREATION DE LA SOCKET *
 -     *************************/
 -    if((hostinfo = gethostbyname(argv[1])) == NULL)
 -       fprintf(stderr, "Et là... c'est le drame !\n" );
 -    server_info.sin_family = AF_INET;    /* We treats with IPv4 address */
 -    server_info.sin_port = htons(5000);
 -    server_info.sin_addr = *((struct in_addr*)hostinfo->h_addr);
 -    memset(&(server_info.sin_zero), '\0', (size_t)8);
 -    if((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
 -       fprintf(stderr, "Error in the socket creation\n" );
 -    printf("ip = %s\n", inet_ntoa(server_info.sin_addr));
 -    /************************
 -     * CONNEXION AU SERVEUR *
 -     ************************/
 -    if (connect(fd, (struct sockaddr *)&server_info, sizeof(struct sockaddr)) ==
 - -1)
 -    {
 -       fprintf(stderr, "Impossible de se connecter au serveur\n" );
 -       exit(EXIT_FAILURE);
 -    }
 -    /**************
 -     * TRANSFERTS *
 -     **************/
 -    /* Envoie d'un msg au serveur */
 -    if (send(fd, msg, strlen(msg), 0) == -1)
 -       fprintf(stderr, "Error while using send()\n" );
 -    printf("Message sent by the client : %s\n", msg);
 -    sleep(2);
 -    if (send(fd, msg, strlen(msg), 0) == -1)
 -       fprintf(stderr, "Error while using send()\n" );
 -    printf("Message sent by the client : %s\n", msg);
 -    close(fd);
 -    return EXIT_SUCCESS;
 - }
 
  |  
 
   Quelqu'un pourrait-il m'aider à résoudre ce problème (tout bete en plus) ?    Message édité par Lockness le 16-04-2004 à 22:10:39
  |