gocho | Bien le bonjour a tous! Voila j'ai cette annee un projet tutore a faire(2e annee de dut info gestion).Pour cela je suis en train de developper un serveur multiclient en C.J'utilise donc les threads et les sockets, et je travaille sous linux (y'aura ptet du windows dans l'affaire plus tard mais c'est optionnel si le temps le permet)
Ne connaissant pas grand chose a la programmation reseau, j'ai cherche sur le net des tuto, des exemples et tout ce qui pouvait m'aider et grace a tout ca et pas mal de temps j'en ai sorti quelquechose qui devrait etre potable (non non c'est pas portable ) Seulement avant de continuer plus loin, et au vu de ma tres petite experience dans la prog reseau je souhaiterai savoir si dans le code de mon serveur, il vous apparait des erreurs grossieres, des failles assez moches ou memes des fuites de memoires.
Enfin je voudrais avoir au final un code si possible le plus propre possible donc je demande un peu d'aide exterieure
Code :
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <unistd.h>
- #include <pthread.h>
- #ifndef LONGUEUR_MAX
- #define LONGUEUR_MAX 256
- #define MAX_CLIENTS 10
- #define NB_FILE_CLIENTS 5
- #define PSEUDO "Bienvenue...\nEntrez votre pseudo : "
- /*erreurs*/
- #define ERR_OPEN_SOCK "Erreur d'ouverture de la socket!\n"
- #define ERR_BIND "Erreur de bind!\n"
- #define ERR_LISTEN "Erreur de listen!\n"
- #define ERR_ALLOCATE_MEM_CLIENT "Erreur d'allocation memoire pour le client!\n"
- #define ERR_PSEUDO "Erreur de pseudo! Celui choisi est deja en cours d'utlisation!\n"
- #define ERR_WRITE "Erreur d'ecriture!\n"
- #define ERR_ALLOCATE_MEM_PSEUDO "Erreur lors de l'allocation memoire pour le pseudo!\n"
- #define ERR_RESEAU "Erreur de reseau!\n"
- #define ERR_ACCEPT "Erreur d'acceptation d'un client\n"
- #endif
- #define PORT 1798
- struct s_client{
- pthread_t id;
- int socket;
- char * pseudo;
- };
- typedef struct s_client client;
- typedef struct sockaddr_in struct_socket;
- client tab_clients[MAX_CLIENTS];
- char nom_serveur[LONGUEUR_MAX];
- int case_libre=0;
- int nb_clients;
- /**************************************************************/
- /* Creation serveur */
- /**************************************************************/
- int creation_serveur(int port){
- /*variables utiles a la creation du serveur*/
- int sock;
- struct_socket adresse_socket;
- /*initialisation du nom du serveur*/
- gethostname(nom_serveur,sizeof(nom_serveur));
- if ((sock=socket(PF_INET,SOCK_STREAM,0))<0){
- printf (ERR_OPEN_SOCK);
- exit(-1);
- }
- /*initialisation du serveur*/
- memset(&adresse_socket,0,sizeof(struct sockaddr_in));
- adresse_socket.sin_family=AF_INET;
- adresse_socket.sin_port=htons(port); // htons convertit un entier court en entier "reseau"
- adresse_socket.sin_addr.s_addr=htonl(INADDR_ANY); // htonl : de meme que htons mais pour un entier long INADDR_ANY=0 -> designe l'adresse du poste sur lequel est lance le programme
- /*affectation d'un nom a la socket*/
- if (bind (sock,(struct sockaddr *)&adresse_socket,sizeof(struct sockaddr_in))<0){
- perror (ERR_BIND);
- exit(-1);
- }
- /*"initialisation" des "options" d'ecoute de la socket*/
- if (listen(sock,NB_FILE_CLIENTS)<0){
- perror (ERR_LISTEN);
- exit(-1);
- }
- return sock;
- }
- /**************************************************************/
- /* Envoi de message a un seul client */
- /**************************************************************/
- int envoi_message(int sock, char * message){
- if ((write(sock,message,strlen(message)))==-1){
- perror(ERR_WRITE);
- return 1;
- }
- return 0;
- }
- /**************************************************************/
- /* Envoi de message a tous les clients sauf celui specifie */
- /**************************************************************/
- int envoi_limite(char * message,int sock){
- int i;
- for (i=0;i<case_libre;i++){
- if(tab_clients[i].socket != sock){
- envoi_message(tab_clients[i].socket,message);
- }
- }
- return 0;
- }
- /**************************************************************/
- /* Envoi d'un message a tous les clients du serveur */
- /**************************************************************/
- int envoi_general(char * message){
- int i;
- for (i=0;i<case_libre;i++){
- envoi_message(tab_clients[i].socket,message);
- }
- return 0;
- }
- /**************************************************************/
- /* Depart d'un client */
- /**************************************************************/
- void client_quit(client * client_courant,char * raison){
- int i,j;
- char buf[8192+1];
- if ((strcmp(raison,'\0'))>0){
- snprintf(buf,8192,"%s part vers d'autres cieux...(%s)\n",client_courant->pseudo,raison);
- }
- else {
- snprintf(buf,8192,"%s part vers d'autres cieux...(%s)\n",client_courant->pseudo,raison);
- }
- envoi_limite(buf,client_courant->socket);
- /*recherche du client dans tab_clients*/
- for (i=0;(tab_clients[i].socket != client_courant->socket);i++);
- /*liberation des ressources du client*/
- close(client_courant->socket);
- free(client_courant->pseudo);
- free(client_courant);
- /*reorganisation de tab_clients*/
- for (j=i+1;j<case_libre;j++){
- tab_clients[j-1]=tab_clients[j];
- }
- case_libre--;
- nb_clients--;
- }
- /**************************************************************/
- /* Acceptation d'un client par le serveur */
- /**************************************************************/
- int client_accepte(int socket_serveur){
- int socket_client;
- if((socket_client = accept(socket_serveur,NULL,0)) < 0)
- {
- if(errno == EINTR)
- {
- shutdown(socket_serveur,SHUT_RDWR);
- close(socket_serveur);
- nb_clients--;
- return -1;
- }
- else
- {
- perror(ERR_ACCEPT);
- exit(-1);
- }
- }
- fcntl(socket_client,F_SETFD,1);
- return socket_client;
- }
- /**************************************************************/
- /* Interaction avec le client : thread */
- /**************************************************************/
- void * thread_client(void *args){
- char pseudo[255];
- char message_emis[8192+1];
- char message_recu[4096+1];
- int case_libre=0;
- int len,i;
- int sock=*((int *)args);
- client *client_courant=NULL;
- if ((client_courant=malloc (sizeof(struct s_client)))==NULL){
- perror (ERR_ALLOCATE_MEM_CLIENT);
- close (sock);
- nb_clients--;
- pthread_exit(NULL);
- }
- envoi_message(sock,PSEUDO);
- len = read(sock,message_recu,4096);
- if(len <= 0) {
- printf("\nErreur\n" );
- close(sock);
- free(me);
- client_courant = NULL;
- nb_clients--;
- pthread_exit(NULL);
- }
- /*recuperation du pseudo du client courant*/
- for (i=0;(pseudo[i]!='\0')&&(pseudo[i]!='\n');i++); //on va a la fin du pseudo
- pseudo[i]='\0'; // on met un \0 pour le terminer proprement
- for (i=0;i<case_libre;i++){
- if (strcmp(pseudo,tab_clients[i].pseudo)==0){ // si strcmp==0 alors les chaines sont identiques
- if ((write(sock,ERR_PSEUDO,strlen(ERR_PSEUDO)))==-1){
- perror(ERR_WRITE);
- }
- close (sock); //fermeture de la socket du client courant
- free(client_courant); //liberation de la memoire allouee pour le client courant
- nb_clients--;
- pthread_exit(NULL);
- }
- }
- /*initialisation de la structure du client courant*/
- if(client_courant->pseudo=malloc(sizeof(pseudo))==NULL){
- perror (ERR_ALLOCATE_MEM_PSEUDO);
- nb_clients--;
- pthread_exit(NULL);
- }
- client_courant->id=pthread_self();
- client_courant->socket=sock;
- strcpy(client_courant->pseudo,pseudo);
- /*placement du client dans le tab_client a la premiere "case libre"*/
- tab_clients[case_libre]=*client_courant;
- case_libre++; //le prochaine case libre du tableau est un rang plus loin
- snprintf(message_emis,8192,"Nouveau Client : %s\n",client_courant->pseudo);
- message_emis[8192]='\0';
- if ((write(sock,message_emis,strlen(message_emis)))==-1){
- perror(ERR_WRITE);
- }
- while (1){
- len=read(sock,message_recu,8192); //read retourne le nombre d'octets lus, -1 en cas d'echec, 0 si rien ou en fin de fichier
- if (len<=0){ //s'il y a erreur de lecture ou fin du message
- client_quit(client_courant,ERR_RESEAU);
- pthread_exit(NULL);
- }
- message_recu[len]='\0';
- snprintf(message_emis,8192,"%s : %s\n",client_courant->pseudo,message_recu);
- message_emis[8192]='\0';
- envoi_general(message_emis);
- }
- return NULL;
- }
- /**************************************************************/
- /* Fonction principale : lancement du serveur */
- /**************************************************************/
- int main(int argc, char **argv)
- {
- int socket_serveur,socket_client;
- pthread_t id;
- socket_serveur = create_server(PORT);
- while(1)
- {
- if ((socket_client = client_accepte(socket_serveur))==-1){
- perror(ERR_ACCEPT);
- exit(-1);
- }
- if(nb_clients < MAX_CLIENTS)
- {
- pthread_create(&id,NULL,thread_client,(void *)&socket_client);
- nb_clients++;
- printf("Nouveau client! Il y a actuellement %d clients sur le serveur\n",nb_clients);
- }
- else close(socket_client);
- }
- return 0;
- }
|
J'avoue c'est un peu long alors je remercie d'avance ceux qui auront la patience de tout lire et de m'aider
Merci Message édité par gocho le 10-11-2005 à 00:14:39
|