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
|