/* fichier: ipc_socket.c * créé le: 29/09/2004 * dernière modification le: 30/09/2004 * auteur: christophe bismuth * sujet : communication inter-processus par sockets (SOCK_STREAM) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include #include <sys/un.h> #include <sys/wait.h> #include <sys/types.h> #include <sys/socket.h> #define NCLIENTS 5 /* nombre de client(s) attendu(s) sur le serveur */ #define NATTEMPTS 100000 /* nombre de tentative(s) de connection(s) sur le serveur (pour chaque client) */ int createUNIXStreamSocketServer(int *st, char *address, int fs[NCLIENTS]) { int from_length; register int length; register int accepted = 0; struct sockaddr_un saun; /* creation de la socket */ if ((*st = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "createUNIXStreamSocketServer: socket() failed\n"); return(1); } else fprintf(stderr, "createUNIXStreamSocketServer: socket created in AF_UNIX domain\n"); /* assignation du domaine de communication */ saun.sun_family = AF_UNIX; /* assignation de l'adresse de connexion */ if (strcpy(saun.sun_path, address) == NULL) { fprintf(stderr, "createUNIXStreamSocketServer: strcpy() failed\n"); close(*st); return(1); } else fprintf(stderr, "createUNIXStreamSocketServer: socket address loaded\n"); /* liberation de l'adresse de connexion */ unlink(address); length = sizeof(saun.sun_family) + strlen(saun.sun_path); /* lien entre la socket et l'adresse de connexion */ if (bind(*st, (struct sockaddr *) &saun, length) < 0) { fprintf(stderr, "createUNIXStreamSocketServer: bind() failed\n"); close(*st); return(1); } else fprintf(stderr, "createUNIXStreamSocketServer: socket named in file system\n"); /* ecoute du serveur de 'backlog' client(s) */ if (listen(*st, NCLIENTS) < 0) { fprintf(stderr, "createUNIXStreamSocketServer: listen() failed\n"); close(*st); return(1); } else fprintf(stderr, "createUNIXStreamSocketServer: %d connection request(s) can be queued\n", NCLIENTS); /* attente des 'backlog' client(s) */ fprintf(stderr, "createUNIXStreamSocketServer: waiting for %d client(s) to connect...\n", NCLIENTS); while(1) { if ((fs[accepted] = accept(*st, (struct sockaddr *) &saun, &from_length)) < 0) { fprintf(stderr, "createUNIXStreamSocketServer: accept() failed for client %d\n", accepted); close(*st); return(1); } else { accepted = accepted + 1; fprintf(stderr, "createUNIXStreamSocketServer: %d client(s) accepted\n", accepted); if (accepted == NCLIENTS) break; } } return(0); } int connectUNIXStreamSocketClient(int *st, char *address) { register int length; register int attempts = 0; struct sockaddr_un saun; /* creation de la socket */ if ((*st = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "connectUNIXStreamSocketClient: socket() failed\n"); return(1); } else fprintf(stderr, "connectUNIXStreamSocketClient: socket created in AF_UNIX domain\n"); /* assignation du domaine de communication */ saun.sun_family = AF_UNIX; /* assignation de l'adresse de connexion */ if (strcpy(saun.sun_path, address) == NULL) { fprintf(stderr, "connectUNIXStreamSocketClient: strcpy() failed\n"); close(*st); return(1); } else fprintf(stderr, "connectUNIXStreamSocketClient: socket address loaded\n"); length = sizeof(saun.sun_family) + strlen(saun.sun_path); /* tentative(s) de connexion au serveur */ while (attempts < NATTEMPTS) { if (connect(*st, (struct sockaddr *) &saun, length) < 0) attempts++; else break; } if (attempts == NATTEMPTS) { fprintf(stderr, "connectUNIXStreamSocketClient: connect() failed\n"); close(*st); return(1); } else fprintf(stderr, "connectUNIXStreamSocketClient: client connected\n"); return(0); } int main(void) { char c; register int i, j; char *address = "stream"; int server_socket; int client_socket[NCLIENTS]; int fs[NCLIENTS]; FILE **fp_server = NULL; FILE **fp_client = NULL; /* allocation memoire de la table de descripteur(s) de ficher(s) du(des) socket(s) acceptee(s) par le serveur */ if (((fp_server) (FILE **) malloc(sizeof(FILE *) * NCLIENTS)) NULL) { fprintf(stderr, "main: malloc() failed for server\n"); exit(1); } else fprintf(stderr, "main: file descriptor(s) for server loaded in memory\n"); /* allocation memoire de la table de descripteur(s) de ficher(s) du(des) socket(s) connectee(s) au serveur */ if ((fp_client (FILE **) malloc(sizeof(FILE *) * NCLIENTS)) NULL) { fprintf(stderr, "main: malloc() failed for client(s)\n"); exit(1); } else fprintf(stderr, "main: file descriptor(s) for client(s) loaded in memory\n"); switch(fork()) { case -1: fprintf(stderr, "main: fork() failed\n"); exit(1); case 0: /* processus fils: connexion(s) du(des) client(s) au serveur */ /* connexion(s) des NCLIENTS au serveur */ for (i = 0; i < NCLIENTS; i++) { if (connectUNIXStreamSocketClient(&client_socket[i], address) != 0) { for (j = 0; j < i; j++) close(client_socket[j]); exit(1); } } /* association(s) flux/descripteur(s) de fichier(s) */ for (i = 0; i < NCLIENTS; i++) { if ((fp_client[i] = fdopen(client_socket[i], "r")) == NULL) { fprintf(stderr, "main: fdopen() failed for client %d\n", i); for(j = 0; j < NCLIENTS; j++) close(client_socket[j]); exit(1); } else fprintf(stderr, "main: client %d stream associated with file descriptor\n", i); } /* lecture(s) du(des) message(s) envoye(s) par le serveur */ for (i = 0; i < NCLIENTS; i++) { while((c = fgetc(fp_client[i])) != EOF) { putchar(c); if (c == '\n') break; } fprintf(stderr, "main: end of server message transmission by client %i\n", i); } fprintf(stderr, "main: end of client process\n"); break; default: /* processus pere: creation du serveur */ /* creation du serveur */ if (createUNIXStreamSocketServer(&server_socket, address, fs) != 0) exit(1); /* association(s) descripteur(s) de socket(s)/descripteur(s) de fichier(s) */ for (i = 0; i < NCLIENTS; i++) { if ((fp_server[i] = fdopen(fs[i], "r")) == NULL) { fprintf(stderr, "main: fdopen() failed for server and client %d\n", i); close(server_socket); wait(0); exit(1); } else fprintf(stderr, "main: server stream associated with file descriptor of client %d\n", i); } /* envoi(s) du(des) message(s) au(x) client(s) */ for (i = 0; i < NCLIENTS; i++) { if (send(fs[i], "server message\n", strlen("server message\n"), 0) < 0) { fprintf(stderr, "main: send() failed for client %d\n", i); close(server_socket); wait(0); exit(1); } else fprintf(stderr, "main: message sent to client %d\n", i); } fprintf(stderr, "main: end of server process\n"); wait(0); break; } /* fermetures des sockets serveur et cliente(s) */ close(server_socket); for(j = 0; j < NCLIENTS; j++) close(client_socket[j]); exit(0); }
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question