begin process at 2012 05 27 18:42:32
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Réseaux & Internet

 > MINICHAT MULTI-CLIENT

MINICHAT MULTI-CLIENT


 Information sur la source

Note :
9 / 10 - par 1 personne
9,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Réseaux & Internet Classé sous :socket, chat, serveur, client, thread Niveau :Débutant Date de création :20/02/2011 Date de mise à jour :02/03/2011 15:52:13 Vu / téléchargé :4 744 / 408

Auteur : wisar

Ecrire un message privé
Commentaire sur cette source (11)
Ajouter un commentaire et/ou une note

 Description

Voila, un mini-chat multithread ,multi client en console, Je poste cet première source, pas pour montrer quelques chose d'innovant mais plutôt pour que les plus expérimenter m'aide a améliorer ma façon de programmer car vous allez surement la trouver un peu barbare notamment l'utilisation de variable globale car je n'arrivai pas a passer des arguments a un thread.
Néanmoins je suis sur que cette source pourra en apprendre beaucoup au débutant sur l'utilisation des sockets car je l'est énormément commenter(un peu trop même,lol).
n'oubliez pas d'inclure la librairie winsock2 ainsi que pthread(la dll est dans le projet).

Source

  • ///////////////////////////////////////////////SERVEUR///////////////////////////////////////////////
  • #include <stdio.h>
  • #include <windows.h>
  • #include <pthread.h>//utilisation des threads
  • #include <winsock2.h>//pour les sockets
  • #define PORT 2000 //le port sur lequel le serveur ecoute
  • #define MAX_CLIENT 3 // cette constante sert a definir le nombre de maximum de client qui sera autoriser par le serveur
  • struct Client//structure ou sera enregistre les information pour chaque client
  • {
  • SOCKET SockClient;// son socket
  • bool Connecte;//si ce client est deja utiliser ou pas (1 si deja utiliser,sinon 0)
  • pthread_t ThreadReception; //son thread de reception( la fonction recv est une fonction "bloquante" donc utilisation de thread
  • char Pseudo[50];//le pseudo du client
  • };
  • Client client[MAX_CLIENT];//tableau de type Client,ou seront stoquer tout les clients
  • int IDNouveauThread=0;//variable temporaire qui me sert a envoyer une variable d'une fonction a une autre( car j'arrive pas a envoyer une variable a une fonction lancer en thread)
  • int ServeurPlein=0;//1:le serveur est plein,0 le serveur a encore des emplacement de libre
  • void *Reception(void *data);//fonction qui ecoute un client et renvoie les donnees recu au autre client
  • int EnvoieDonnee(SOCKET SockClient,char *Donnee);/*envoie donnee au client
  • renvoie 1 si tout c'est bien passer sinon revoie 0*/
  • int Ecoute();/*fonction qui met en ecoutesur le port selectionne plus haut(attente de client)
  • revoie 1 si l'ecoute a ete lancer avec succes
  • sinon revoie 0*/
  • SOCKET SockServeur;
  • int Retour=0;
  • SOCKADDR_IN Sin = {0};
  • int main(void)
  • {
  • int I=0;
  • if (Ecoute())//on lance l'ecoute sur le port(defini plus haut)
  • {
  • printf("Le Serveur ecoute sur le port %d\nEn attente de la connections des clients\n",PORT);//si 1, c ok
  • }
  • else
  • {
  • printf("Erreur lors de la mise en ecoute sur le port no %d\n",PORT);//0 erreur, on est obliger de sortir
  • system("pause");
  • return 0;
  • }
  • I=0;//variable qui va servir a parcourir le tableau de Client
  • do
  • {
  • if (I>=MAX_CLIENT)//veut dire que l'on a atteint la limite maxi des clients
  • {
  • printf("Serveur Plein\n");
  • ServeurPlein=1;//on indique que le Serveur est saturer
  • shutdown(SockServeur, 1);//on eteint le socket de reception
  • closesocket(SockServeur);//idem
  • do
  • {
  • Sleep(1000);//sert a evite de charger le processeur
  • }
  • while (ServeurPlein);//temps que la variable ServeurPlein est a 1 cela veut dire que aucun emplacement a ete liberer
  • //un emplacement a ete liberer
  • if (Ecoute())//on relance l'ecoute
  • {
  • printf("Serveur en attente de client\n");
  • }
  • else
  • {
  • printf("Erreur lors de la mise en ecoute sur le port no %d\n",PORT);
  • system("pause");
  • return 0;
  • }
  • I=0;//on remet i a 0 pour la prochaine recherche
  • }
  • else
  • {
  • if (client[I].Connecte==false)//veut dire que cette emplacement de client n'est pas utiliser, donc OK
  • {
  • printf("Emplacement libre trouver:%d\n",I);
  • Sleep(10);
  • SOCKADDR_IN CSin = {0};
  • int sizeofcsin = sizeof(CSin);
  • client[I].SockClient = accept(SockServeur, (SOCKADDR *)&CSin, &sizeofcsin);//on accepte la connection
  • if ( client[I].SockClient != INVALID_SOCKET )//si la connection a reussi
  • {
  • client[I].Connecte=true;//on passe la variable a 1 pour indique que se client est dorenavant utilise
  • Retour = recv(client[I].SockClient, client[I].Pseudo, sizeof(client[I].Pseudo)-1, 0);//on recoit le pseudo
  • printf("Client no %d connecte sous le pseudo: %s\n\n",I,client[I].Pseudo);
  • IDNouveauThread=I;//je passe ma variable i dans une variable temporaire pour savoir sur quelle client je doit ecouter pour la fonction suivante
  • pthread_create(&client[I].ThreadReception, NULL, Reception, NULL);//on lance le thread ou va etre recu les donnes de se client
  • I=0;//on repasse i a 0 pour une prochaine recherche d'emplacement libre
  • }
  • else
  • {
  • printf("Erreur\n");
  • }
  • }
  • I++;//on poursuit la recherche de nouveau client
  • }
  • }
  • while (1);
  • WSACleanup();
  • system("pause");
  • return 0;
  • }
  • void *Reception(void *Donnee)
  • {
  • int RetourReception;
  • int I=0;
  • int IDThreadActuel=IDNouveauThread;
  • char DonneeRecu[1024];//variable ou sera stocker les donnees recu
  • char DonneeAEnvoyer[1024];
  • int Connecte=true;//la conection au serveur est ok
  • do
  • {
  • I=0;// variable qui va servir a parcourir les clients auquel on va envoyer les donnees recu d'un client
  • RetourReception = recv(client[IDThreadActuel].SockClient, DonneeRecu, sizeof(DonneeRecu)-1, 0);//on recoit les donnees(fonction "bloquante"
  • if (RetourReception != SOCKET_ERROR)//connection avec le client OK
  • {
  • DonneeRecu[RetourReception] = '\0';
  • do
  • {
  • if (client[I].Connecte==true)//cela veut dire que se client est connecte donc on peut lui envoyer les donnees que l'on vient de recevoir
  • {
  • if (I!=IDThreadActuel)//pour ne pas envoyer les donnees au client qui vient de les envoyer(ben oui on sait se que l'on vient de taper lol)
  • {
  • DonneeAEnvoyer[0]='\0';
  • strcat(DonneeAEnvoyer,client[IDThreadActuel].Pseudo);
  • strcat(DonneeAEnvoyer," dit: ");
  • strcat(DonneeAEnvoyer,DonneeRecu);
  • if (!EnvoieDonnee(client[I].SockClient,DonneeAEnvoyer))//si l'envoie de donnee a echouer
  • {
  • printf("%s deconnecte\n",client[I].Pseudo);
  • closesocket(client[I].SockClient);//on ferme son socket client
  • client[I].Connecte=false;//on indique que cet emplacement est desormais libre
  • ServeurPlein=0;//le serveur n'est plus plein si il l'etait(je sais j'aurais pu mettre un if pour verifier si il l'etait...)
  • }
  • }
  • }
  • I++;//on continue a parcourir les autres clients
  • }
  • while (I<MAX_CLIENT);//tant que l'on a pas atteind la limite de client
  • I=0;//pour une prochaine recherche lors de la prochaine reception de donnee
  • }
  • else//connection avec le client NOK
  • {
  • printf("%s deconnecte\n",client[IDThreadActuel].Pseudo);
  • shutdown(client[IDThreadActuel].SockClient, 2);//on ferme le socket de se thread
  • closesocket(client[IDThreadActuel].SockClient);//idem
  • client[IDThreadActuel].Connecte=false;//on indique que cet emplacement est desormais libre
  • ServeurPlein=0;//voir plus haut
  • Connecte=false;//on sort de la boucle pour terminer le thread puisque l'on a perdu la connection avec ce client
  • }
  • }
  • while (Connecte);
  • return &Donnee;
  • }
  • int EnvoieDonnee(SOCKET SockClient,char *Donnee)
  • {
  • int RetourEnvoie;
  • RetourEnvoie=send(SockClient, Donnee, strlen(Donnee), 0);//envoie les donnee (variable data)
  • if (RetourEnvoie!=SOCKET_ERROR)
  • {
  • return 1;
  • }
  • return 0;
  • }
  • int Ecoute()
  • {
  • WSADATA WSAData;
  • WSAStartup(MAKEWORD(2,0), &WSAData);//init winsock
  • SOCKADDR_IN Sin = {0};//structure qui va contenir les informations de notre socket serveur
  • SockServeur = socket(AF_INET, SOCK_STREAM, 0);//creation du socket
  • if ( SockServeur != INVALID_SOCKET )//si creation ok
  • {
  • Sin.sin_addr.s_addr = htonl(INADDR_ANY);//on rempli la structure
  • Sin.sin_family = AF_INET;//idem
  • Sin.sin_port = htons(PORT);//idem
  • Retour = bind(SockServeur, (SOCKADDR *)&Sin, sizeof(Sin));//on associe le socket a notre adresse local(enfin je crois,lol)
  • if ( Retour != SOCKET_ERROR )//si ok
  • {
  • Retour = listen(SockServeur, 2);//on commence ll'ecoute (l'attente de client)
  • if ( Retour != SOCKET_ERROR )//si tout c'est bien passer
  • {
  • return 1;
  • }
  • }
  • }
  • return 0;
  • }
  • /////////////////////////////////////////////////////////////////////////////////////////////////////
  • //////////////////////////////////////////////CLIENT////////////////////////////////////////////////
  • #include <stdio.h>
  • #include <windows.h>
  • #include <winsock2.h>
  • #include <pthread.h>//utilisation des thread car fonction recv bloquante
  • #define TPSATTENTE 5
  • SOCKET Sock;
  • pthread_t ThreadReception;
  • void *Reception(void *Donnee);//fonction ou se fait la reception de donnee envoyer par le serveur
  • int main(void)
  • {
  • char Ip[16];
  • unsigned int Port=0;
  • char Pseudo[50];
  • int Erreur;
  • int TempsDAttente=0;
  • bool Connecte=false;
  • printf("\t\t\t\tClient multiThread\n\n\n");
  • WSADATA WSAData;
  • WSAStartup(MAKEWORD(2,0), &WSAData);//init winsock
  • printf("Choisir un Pseudo:\n");// un pseudo
  • Pseudo[0]='\0';
  • fgets(Pseudo,sizeof Pseudo,stdin);
  • Pseudo[strlen(Pseudo)-1]='\0';//pour retirer le retour chariot qui est enregistre dans le fgets
  • printf("Adresse du serveur:\n"); //on recupere les differente infos, adresse
  • Ip[0]='\0';
  • fgets(Ip,sizeof Ip,stdin);
  • Ip[strlen(Ip)-1]='\0';//pour retirer le retour chariot qui est enregistre dans le fgets
  • printf("Port de connection:\n"); //port de connection
  • scanf("%d",&Port);
  • Sock = socket(AF_INET, SOCK_STREAM, 0);//on creer le socket
  • if ( Sock != INVALID_SOCKET )//si creation ok
  • {
  • printf("\nSocket client no %d ouvert\n",Sock);
  • SOCKADDR_IN Sin;
  • Sin.sin_addr.s_addr = inet_addr(Ip); //on rempli la structure sin qui va servir au socket
  • Sin.sin_family = AF_INET;
  • Sin.sin_port = htons(Port);
  • printf("Connection a %s sur le port %d en cours...\n",Ip,Port);
  • do
  • {
  • Erreur = connect(Sock, (SOCKADDR *)&Sin, sizeof Sin);//on essaye de se connecte au serveur
  • if (Erreur != SOCKET_ERROR)
  • {
  • Connecte=true;
  • }
  • else
  • {
  • if (TempsDAttente<=TPSATTENTE)
  • {
  • Sleep(1000);// on attend 1 seconde avant de reesayer (pour eviter de charge le processeur
  • TempsDAttente++;
  • }
  • else
  • {
  • printf("Temps de connection trop long");
  • goto deconnection;
  • }
  • }
  • }
  • while (!Connecte);//tant que l'on arrive pas a se connecter
  • printf("Connection au serveur effectue avec succes\n\n");
  • char DonneeAEnvoyer[512];
  • Erreur = send(Sock, Pseudo, strlen(Pseudo), 0);//on envoie le pseudo au serveur
  • if (Erreur == SOCKET_ERROR)//si il y a erreur cela veut dire que l'on a perdu la connection avec le serveur donc on sort
  • {
  • goto deconnection;
  • }
  • pthread_create(&ThreadReception, NULL, Reception, NULL);//on lance le thread qui va recevoir les donnees du serveur
  • do
  • {
  • DonneeAEnvoyer[0]='\0';//pour etre sur de ne pas envoyer autre chose que se qui a ete saisie
  • fgets(DonneeAEnvoyer, sizeof DonneeAEnvoyer, stdin);//on recupere les saisies du clavier
  • Erreur = send(Sock, DonneeAEnvoyer, strlen(DonneeAEnvoyer), 0);//on les envoie au serveur
  • if (Erreur == SOCKET_ERROR)
  • {
  • Connecte=false;//si erreur, on sort de la boucle
  • }
  • }
  • while (Connecte);
  • deconnection:
  • printf("Connection avec le serveur interrompu\n");
  • closesocket(Sock);//on ferme le socket
  • }
  • else
  • {
  • printf("Socket invalide\n");
  • return EXIT_FAILURE;
  • }
  • WSACleanup();//on nettoie le wsa.
  • system("pause");
  • return EXIT_SUCCESS;
  • }
  • void *Reception(void *Donnee)
  • {
  • int Erreur;
  • bool Connecte=true;
  • char DonneeRecu[50];
  • do
  • {
  • Erreur = recv(Sock, DonneeRecu, sizeof(DonneeRecu)-1, 0);//on recoit les donnees, fonction bloquante d'ou le thread
  • if (Erreur == SOCKET_ERROR)
  • {
  • Connecte=false;//voir plus haut
  • }
  • else
  • {
  • DonneeRecu[Erreur] = '\0';
  • printf(">>>> %s",DonneeRecu);
  • }
  • }
  • while (Connecte);
  • printf("perte de la connection avec le serveur\n");
  • closesocket(Sock);//on ferme le socket
  • return &Donnee;
  • }
  • //////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////SERVEUR///////////////////////////////////////////////
#include <stdio.h>

#include <windows.h>
#include <pthread.h>//utilisation des threads
#include <winsock2.h>//pour les sockets

#define PORT 2000 //le port sur lequel le serveur ecoute
#define MAX_CLIENT 3 // cette constante sert a definir le nombre de maximum de client qui sera autoriser par le serveur

struct Client//structure ou sera enregistre les information pour chaque client
{
    SOCKET SockClient;// son socket
    bool Connecte;//si ce client est deja utiliser ou pas (1 si deja utiliser,sinon 0)
    pthread_t ThreadReception; //son thread de reception( la fonction recv est une fonction "bloquante" donc utilisation de thread
    char Pseudo[50];//le pseudo du client
};

Client client[MAX_CLIENT];//tableau  de type Client,ou seront stoquer tout les clients

int IDNouveauThread=0;//variable temporaire qui me sert a envoyer une variable d'une fonction a une autre( car j'arrive pas a envoyer une variable a une fonction lancer en thread)
int ServeurPlein=0;//1:le serveur est plein,0 le serveur a encore des emplacement de libre


void *Reception(void *data);//fonction qui ecoute un client et renvoie les donnees recu au autre client
int EnvoieDonnee(SOCKET SockClient,char *Donnee);/*envoie donnee au client
                                                  renvoie 1 si tout c'est bien passer sinon revoie 0*/
int Ecoute();/*fonction qui met en ecoutesur le port selectionne plus haut(attente de client)
               revoie 1 si l'ecoute a ete lancer avec succes
               sinon revoie 0*/

SOCKET SockServeur;
 int Retour=0;
 SOCKADDR_IN Sin = {0};






int main(void)
{


    int I=0;




    if (Ecoute())//on lance l'ecoute sur le port(defini plus haut)
    {
        printf("Le Serveur ecoute sur le port %d\nEn attente de la connections des clients\n",PORT);//si 1, c ok
    }
    else
    {
        printf("Erreur lors de la mise en ecoute sur le port no %d\n",PORT);//0 erreur, on est obliger de sortir
        system("pause");
        return 0;
    }











    I=0;//variable qui va servir a parcourir le tableau de Client

    do
    {

        if (I>=MAX_CLIENT)//veut dire que l'on a atteint la limite maxi des clients
        {
            printf("Serveur Plein\n");
            ServeurPlein=1;//on indique que le Serveur est saturer
            shutdown(SockServeur, 1);//on eteint le socket de reception
            closesocket(SockServeur);//idem


            do
            {

                Sleep(1000);//sert a evite de charger le processeur
            }
            while (ServeurPlein);//temps que la variable ServeurPlein est a 1 cela veut dire que aucun emplacement a ete liberer
            //un emplacement a ete liberer
            if (Ecoute())//on relance l'ecoute
            {
                printf("Serveur en attente de client\n");
            }
            else
            {
                printf("Erreur lors de la mise en ecoute sur le port no %d\n",PORT);
                system("pause");
                return 0;
            }
            I=0;//on remet i a 0 pour la prochaine recherche
        }
        else
        {
            if (client[I].Connecte==false)//veut dire que cette emplacement de client n'est pas utiliser, donc OK
            {

                printf("Emplacement libre trouver:%d\n",I);
                Sleep(10);
                SOCKADDR_IN CSin = {0};
                int sizeofcsin = sizeof(CSin);

                client[I].SockClient = accept(SockServeur, (SOCKADDR *)&CSin, &sizeofcsin);//on accepte la connection

                if ( client[I].SockClient != INVALID_SOCKET )//si la connection a reussi
                {
                    client[I].Connecte=true;//on passe la variable a 1 pour indique que se client est dorenavant utilise
                    Retour = recv(client[I].SockClient, client[I].Pseudo, sizeof(client[I].Pseudo)-1, 0);//on recoit le pseudo
                    printf("Client no %d connecte sous le pseudo: %s\n\n",I,client[I].Pseudo);
                    IDNouveauThread=I;//je passe ma variable i dans une variable temporaire pour savoir sur quelle client je doit ecouter pour la fonction suivante
                    pthread_create(&client[I].ThreadReception, NULL, Reception, NULL);//on lance le thread ou va etre recu les donnes de se client
                    I=0;//on repasse i a 0 pour une prochaine recherche d'emplacement libre

                }
                else
                {
                    printf("Erreur\n");

                }


            }
            I++;//on poursuit la recherche de nouveau client
        }









    }
    while (1);

WSACleanup();
    system("pause");
    return 0;
}

void *Reception(void *Donnee)
{
    int RetourReception;
    int I=0;
    int IDThreadActuel=IDNouveauThread;
    char DonneeRecu[1024];//variable ou sera stocker les donnees recu
    char DonneeAEnvoyer[1024];
    int Connecte=true;//la conection au serveur est ok

    do
    {
        I=0;// variable qui va servir a parcourir les clients auquel on va envoyer les donnees recu d'un client
        RetourReception = recv(client[IDThreadActuel].SockClient, DonneeRecu, sizeof(DonneeRecu)-1, 0);//on recoit les donnees(fonction "bloquante"
        if (RetourReception != SOCKET_ERROR)//connection avec le client OK
        {
            DonneeRecu[RetourReception] = '\0';
            do
            {
                if (client[I].Connecte==true)//cela veut dire que se client est connecte donc on peut lui envoyer les donnees que l'on vient de recevoir
                {
                    if (I!=IDThreadActuel)//pour ne pas envoyer les donnees au client qui vient de les envoyer(ben oui on sait se que l'on vient de taper lol)
                    {

                        DonneeAEnvoyer[0]='\0';
                        strcat(DonneeAEnvoyer,client[IDThreadActuel].Pseudo);
                        strcat(DonneeAEnvoyer," dit: ");
                        strcat(DonneeAEnvoyer,DonneeRecu);
                        if (!EnvoieDonnee(client[I].SockClient,DonneeAEnvoyer))//si l'envoie de donnee a echouer
                        {
                            printf("%s deconnecte\n",client[I].Pseudo);
                            closesocket(client[I].SockClient);//on ferme son socket client
                            client[I].Connecte=false;//on indique que cet emplacement est desormais libre
                            ServeurPlein=0;//le serveur n'est plus plein si il l'etait(je sais j'aurais pu mettre un if pour verifier si il l'etait...)

                        }
                    }
                }

                I++;//on continue a parcourir les autres clients


            }
            while (I<MAX_CLIENT);//tant que l'on a pas atteind la limite de client
            I=0;//pour une prochaine recherche lors de la prochaine reception de donnee
        }
        else//connection avec le client NOK
        {
            printf("%s deconnecte\n",client[IDThreadActuel].Pseudo);
            shutdown(client[IDThreadActuel].SockClient, 2);//on ferme le socket de se thread
            closesocket(client[IDThreadActuel].SockClient);//idem
            client[IDThreadActuel].Connecte=false;//on indique que cet emplacement est desormais libre
            ServeurPlein=0;//voir plus haut


            Connecte=false;//on sort de la boucle pour terminer le thread puisque l'on a perdu la connection avec ce client
        }
    }
    while (Connecte);

    return &Donnee;
}



int EnvoieDonnee(SOCKET SockClient,char *Donnee)
{
    int RetourEnvoie;


    RetourEnvoie=send(SockClient, Donnee, strlen(Donnee), 0);//envoie les donnee (variable data)
    if (RetourEnvoie!=SOCKET_ERROR)
    {
        return 1;
    }

    return 0;
}



int Ecoute()
{
    WSADATA WSAData;
    WSAStartup(MAKEWORD(2,0), &WSAData);//init winsock
    SOCKADDR_IN Sin = {0};//structure qui va contenir les informations  de notre socket serveur


    SockServeur = socket(AF_INET, SOCK_STREAM, 0);//creation du socket

    if ( SockServeur != INVALID_SOCKET )//si creation ok
    {


        Sin.sin_addr.s_addr    = htonl(INADDR_ANY);//on rempli la structure
        Sin.sin_family    = AF_INET;//idem
        Sin.sin_port    = htons(PORT);//idem


        Retour = bind(SockServeur, (SOCKADDR *)&Sin, sizeof(Sin));//on associe le socket a notre adresse local(enfin je crois,lol)
        if ( Retour != SOCKET_ERROR )//si ok
        {
            Retour = listen(SockServeur, 2);//on commence ll'ecoute (l'attente de client)
            if ( Retour != SOCKET_ERROR )//si tout c'est bien passer
            {


                return 1;


            }

        }
    }



    return 0;

}









/////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////CLIENT////////////////////////////////////////////////
#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <pthread.h>//utilisation des thread car fonction recv bloquante

#define TPSATTENTE 5


SOCKET Sock;
pthread_t ThreadReception;

void *Reception(void *Donnee);//fonction ou se fait la reception de donnee envoyer par le serveur

int main(void)
{
    char Ip[16];
    unsigned int Port=0;
    char Pseudo[50];
    int Erreur;
    int TempsDAttente=0;
    bool Connecte=false;


    printf("\t\t\t\tClient multiThread\n\n\n");
    WSADATA WSAData;
    WSAStartup(MAKEWORD(2,0), &WSAData);//init winsock

    printf("Choisir un Pseudo:\n");// un pseudo
    Pseudo[0]='\0';
    fgets(Pseudo,sizeof Pseudo,stdin);
    Pseudo[strlen(Pseudo)-1]='\0';//pour retirer le retour chariot qui est enregistre dans le fgets
    printf("Adresse du serveur:\n"); //on recupere les differente infos, adresse
    Ip[0]='\0';
    fgets(Ip,sizeof Ip,stdin);
    Ip[strlen(Ip)-1]='\0';//pour retirer le retour chariot qui est enregistre dans le fgets
    printf("Port de connection:\n");  //port de connection
    scanf("%d",&Port);



    Sock = socket(AF_INET, SOCK_STREAM, 0);//on creer le socket
    if ( Sock != INVALID_SOCKET )//si creation ok
    {

        printf("\nSocket client no %d ouvert\n",Sock);

        SOCKADDR_IN Sin;
        Sin.sin_addr.s_addr    = inet_addr(Ip); //on rempli la structure sin qui va servir au socket
        Sin.sin_family    = AF_INET;
        Sin.sin_port    = htons(Port);
        printf("Connection a %s sur le port %d en cours...\n",Ip,Port);

        do
        {

            Erreur = connect(Sock, (SOCKADDR *)&Sin, sizeof Sin);//on essaye de se connecte au serveur
            if (Erreur != SOCKET_ERROR)
            {
                Connecte=true;
            }
            else
            {
                if (TempsDAttente<=TPSATTENTE)
                {
                    Sleep(1000);// on attend 1 seconde avant de reesayer (pour eviter de charge le processeur
                    TempsDAttente++;
                }
                else
                {
                    printf("Temps de connection trop long");
                    goto deconnection;

                }
            }
        }
        while (!Connecte);//tant que l'on arrive pas a se connecter





        printf("Connection au serveur effectue avec succes\n\n");


        char DonneeAEnvoyer[512];
        Erreur = send(Sock, Pseudo, strlen(Pseudo), 0);//on envoie le pseudo au serveur
        if (Erreur == SOCKET_ERROR)//si il y a erreur cela veut dire que l'on a perdu la connection avec le serveur donc on sort
        {
            goto deconnection;
        }
        pthread_create(&ThreadReception, NULL, Reception, NULL);//on lance le thread qui va recevoir les donnees du serveur
        do
        {

            DonneeAEnvoyer[0]='\0';//pour etre sur de ne pas envoyer autre chose que se qui a ete saisie
            fgets(DonneeAEnvoyer, sizeof DonneeAEnvoyer, stdin);//on recupere les saisies du clavier
            Erreur = send(Sock, DonneeAEnvoyer, strlen(DonneeAEnvoyer), 0);//on les envoie au serveur
            if (Erreur == SOCKET_ERROR)
            {
                Connecte=false;//si erreur, on sort de la boucle
            }



        }
        while (Connecte);
deconnection:

        printf("Connection avec le serveur interrompu\n");
        closesocket(Sock);//on ferme le socket



    }
    else
    {
        printf("Socket invalide\n");
        return EXIT_FAILURE;
    }


    WSACleanup();//on nettoie le wsa.

    system("pause");
    return EXIT_SUCCESS;
}


void *Reception(void *Donnee)
{
    int Erreur;
    bool Connecte=true;
    char DonneeRecu[50];
    do
    {
        Erreur = recv(Sock, DonneeRecu, sizeof(DonneeRecu)-1, 0);//on recoit les donnees, fonction bloquante d'ou le thread
        if (Erreur == SOCKET_ERROR)
        {
            Connecte=false;//voir plus haut
        }
        else
        {
            DonneeRecu[Erreur] = '\0';

            printf(">>>> %s",DonneeRecu);
        }
    }
    while (Connecte);

    printf("perte de la connection avec le serveur\n");
    closesocket(Sock);//on ferme le socket
    return &Donnee;

}

//////////////////////////////////////////////////////////////////////////////////////////////////////









 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !
  •   ChatMultiClient
    •   Client
      •   bin
        • Debug
      •   obj
        •   Debug
          • main.oTélécharger ce fichier [Réservé aux membres club]724 848 octets
      • Client.cbpTélécharger ce fichier [Réservé aux membres club]1 231 octets
      • Client.dependTélécharger ce fichier [Réservé aux membres club]164 octets
      • Client.layoutTélécharger ce fichier [Réservé aux membres club]239 octets
      • main.cppTélécharger ce fichier [Réservé aux membres club]Voir ce fichier4 334 octets
    •   ServeurMultiThread
      •   bin
        • Debug
      •   obj
        •   Debug
          • main.oTélécharger ce fichier [Réservé aux membres club]727 008 octets
      • main.cppTélécharger ce fichier [Réservé aux membres club]Voir ce fichier8 942 octets
      • ServeurMultiThread.cbpTélécharger ce fichier [Réservé aux membres club]1 267 octets
      • ServeurMultiThread.dependTélécharger ce fichier [Réservé aux membres club]304 octets
      • ServeurMultiThread.layoutTélécharger ce fichier [Réservé aux membres club]238 octets
    • pthreadGC2.dllTélécharger ce fichier [Réservé aux membres club]60 273 octets

Télécharger le zip


 Historique

20 février 2011 16:53:02 :
visionnage du code sans telecharger le zip
02 mars 2011 15:52:22 :
-le temps d'attente de connections du client n'est plus infini mais est définie avec la constante TPSATTENTE -Toutes les variables ont bien ete mis en français(quelque unes étaient en anglais) -j'ai essayer de garder une certaine logique en renommant mes variable(majuscule a tout les début de mot -variable int Connecte transformer en bool(vu qu'il prenait que 2 état diffèrent.

 Sources du même auteur

Source avec Zip PETITE CLASSE DE GESTION DES PROCESSUS SOUS WINDOWS
Source avec Zip KEYLOGGER AVEC NOM DU PROCESSUS ET DE LA FENETRE QUI A LE FO...

 Sources de la même categorie

Source avec Zip Source avec une capture MINI SERVEUR HTTP [WINDOWS] par ganjarasta
Source avec Zip Source avec une capture CLIENT DE TEST MODBUS TCP par brunovan
Source avec Zip Source avec une capture SCANIP [ARP / ICMP] par ganjarasta
Source avec Zip Source avec une capture TRACEROUTE [WINPCAP] par ganjarasta
Source avec Zip SERVEUR MULTITHREAD [LINUX/WIN] par nipepsinicolas

 Sources en rapport avec celle ci

Source avec Zip INTÉGRATION SIMPLE D'UN CLIENT IRC À UNE APPLICATION par PJulot
Source avec Zip Source avec une capture CLIENT/SERVEUR UTILISANT LES IOCP RÉALISÉ AVEC BORLAND BUILD... par goodboy21
Source avec Zip SERVEUR/CLIENT LINUX par ghost4
Source avec Zip MINI CHAT C/C++ par edf102
Source avec Zip MINI CHAT SOCKET par rtfm321

Commentaires et avis

Commentaire de wisar le 26/02/2011 21:58:56

un peu déçu, lol pas de petit commentaire, je pensais déchainer les foule avec mon prog lol.

Commentaire de kertimanoff le 28/02/2011 08:46:34 9/10

Salut, bon j'suis pas un pro, t'a source m'intéresse donc je jette un oeil, et puis comme tu veux un commentaire alors:
dans t'a structure client, la variable Connecte n'a que 2 état possible (0 ou 1), alors pourquoi pas bool plutôt que int ?
Bon courage, en espérant que des vrai pro viennent faire la mega critique (constructive) de ta source !

Commentaire de wisar le 01/03/2011 16:54:57

c'est vrai, je n'y avait pas pensé, je prends ta remarque en compte et si d'autre gens voient d'autre modification a faire j'ajouterai la tienne en même temps

Commentaire de frozon le 02/03/2011 09:12:26

Salut,
Pour bien faire, et vu que ce n'est pas trop trop de changement, il aurait était sympa de voir un code win32/linux
L'initialisation est la même juste besoin d'enelever les WSA* et de rajouter quelque #ifdef

Ensuite, pour ma part je plus suis partisan du memset dans ce cas: bufferSend[0]='\0';
memset(bufferSend, '\0', 512);

C'est aussi dommage que tu face une boucle qui peut etre infini dans ce cas ci:
do
{
    error = connect(sock, (SOCKADDR *)&sin, sizeof sin);//on essaye de se connecte au serveur
    Sleep(1000);// on attend 1 seconde avant de reesayer (pour eviter de charge le processeur
}
while (error == SOCKET_ERROR);//tant que l'on arrive pas a se connecter

Tu devrais mettre en place un nombre maximal de tentative, ce serait plus propre.

Mais bon la chose qui me choque le plus ce sont les nom de méthode en français, les nom de variable un coup en français, un coup en anglais.
Pour ma part je ne suis pas pour du code en français mais ce n'est qu'un avis personnel sachant que tout développeur doit être en mesure et lire et écrire de l'anglais pour uniformiser son code mais aussi lire les docs. Pour les messages que tu affiches en console par contre je suis d'accord qu'ils peuvent rester en français bien sur ;)

Concernant aussi les noms de variable, certains commence par une minuscule, d'autres par une majuscule, idem, pour plus de propreté il faudrait homogénéiser tout cela.

Pour les commentaires, c'est pas trop trop mal il y en a et plus ou moins constructif c'est une bonne chose, la seul chose à noter c'est que pour savoir ce que fait une fonction et ce qu'elle retourne on est obliger de la lire de A à Z. Ce pourrait être pas mal d'avoir un commentaire multi ligne en début de fonction pour pousser le vice jusqu'au bout ;)

Sinon dans l'ensemble c'est pas trop trop mal, reste a bouquiner un peu la doc sur les threads :p

Commentaire de wisar le 02/03/2011 14:48:11

ah ben voila sa c'est du comentaire.
Alors quelques explication, je cherche en rien a m'excuser, je sais que j'ai plaint de defauts en prog.
Alors tout d'abord je parle et ecrit l'anglais assez bien(je tiendrai pas une convers de 2 heure avec un british mais bon)
pour se qui est des variables et fonction en francais, c'est que je trouve dommage que aucun prog soit ecrit en francais mais quasi tout le temps en anglais, n'ayons pas honte de notre langue lol, mais comme tu la dit c'est une histoire de gout.
Par contre c'est vrai qu'au niveau " des regles orthographique" tel que majuscule ou pas majuscule sur les variables j'avoue que c'est du grand n'importe quoi et je vai essayer de me corriger
Pour se qui est des variables anglais/francais en fait je me suis appuyer sur un autre bout de prog ou les variables etaient en anglais et j'ai pas pris la peine de les changer.
Bon fini les explications place a la programation.
merci encore.

Commentaire de frozon le 02/03/2011 14:57:48

[parenthèse hors sujet mais pas trop]
C'est plus qu'une histoire de gout pour l'anglais dans le code quelque language de programmation offre du code 100% en français.
Ex: Si, fin de si, Boucle, fin de boucle, tant que, fin tant que (dans 4D par exemple)
Après a mon avis c'est plus cohérent d'avoir while(alive) {} plutôt que if(en_vie){}
[/parenthèse]

Commentaire de wisar le 02/03/2011 15:54:35

lol oui c'est peut etre un peut vrai, j'ai essayer de corriger au mieux mon code en suivant tes conseil, si tu voit autre chose n'hesite pas lache toi.lol

Commentaire de Rotsycs le 10/01/2012 08:23:50

lu!
je suis en train d'élaborer un programme de tchat en java netbeans maintenant et j'ai un petit soucis concernant l'authentification du client dans la base de données du serveur!
svp! si vous pouvez m'aider! c serai vraiment cool!

Commentaire de wisar le 16/01/2012 08:35:14

dsl je ne pourrai pas t'aider car je ne connais pas le java

Commentaire de andoid le 23/04/2012 16:56:10

Je sais que ce poste date de 2011 mais voila j'essaye de comprendre ton code pour je voulais modifier ton code genre la réception ne vient pas du client qui vient juste de se connecter mais de n'importe quel client comment dois je faire
Merci

Commentaire de wisar le 23/05/2012 10:39:40

je comprends pas se que tu veux dire, la réception des messages? car quand un des client envoie un message tout les autres clients connectes le reçoivent.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Thread & Socket [ par katerson ] Bonjour tout le monde! Je travaille actuellement sur un projet serveur/client sur UDP. Mon serveur comporte 3 threads qui doivent scruter (indépenda [C.] 2 Problèmes sur le serveur [ par Adict ] bonsoir tout le monde. [^^happy13] alors ça va faire vraiment longtemps que je patine sur mon serveur. J'ai cherché et cherché pour le 2ème problème plantage du serveur [ par Adict ] Bonjour [^^happy13] alors voila j'ai fini un projet mais il y a un problème. Il se compose d'une application client et serveur. Il y a quelque temps socket en C sous Qt [ par taifone ] je developpe une application client/serveur en C.Le client est une interface graphique en Qt et le serveur est un programme serveur.c sous linux j'ai application client serveur avec les socket en c [ par zizodev ] Bonjour à tous,mon problème est comment créer une application 'qui demande'.Programme client et autre serveur client  'qui demande' :Pour se connecter Meilleur solution pour serveur MMORPG. [ par LA_Tupac ] Bonjour à tous! voila ma question: Je développe actuellement mon premier jeu en réseau. Le socket d'envoi du client est en tcp et le socket d'envoi du Tutorial - Socket, serveur, client BCPP + GUI [ par NyxArm ] Bonjours tout le monde, je suis présentement en période d'appretissage du language CPP sur Borland(v.6). Maintenant que j'ai acquis quelque conna Evènement sur un socket client [ par darsh99 ] J'aimerais savoir si la méthode utilisée par BlackGoddess pour son serveur (http://www.cppfrance.com/article.aspx?ID=1287) est récupérable pour gérer Thread et socket besoin de conseil [ par kawito ] Salut,je desire realiser un client/serveur TCPle probleme est que les fonctions accept et recv sont bloquante.donc cela bloque l'affichage etc...mon p Programmer un chat avec un serveur en java et un client en c++ [ par Snake655 ] J'aimerais savoir si déjà c'est possible (je pense que oui quand meme :-D) et si oui, que vous m'eclaireriez sur la méthode. Mon but serait de creer u


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,577 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales