Cette source présente la librairie TIM_Reseau basée sur les sockets qui gèrent un réseau à haut niveau
(serveur et client multi-thread, protocoles TCP et UDP, template pour faciliter la gestion des
données, stockage des messages, gestions des clients etc...). Regarder Doc TIM_Reseau.txt pour plus d'informations.
La source est abondamment commentée.
Les deux projets client et serveur sont codés sous code::block compilés sous windows.
Je laisse le projet code::block pour ceux qui l'aurait.
Ces projets illustrent les classes TIM_server et TIM_client par l'exemple d'un chat
exploitant les 2 protocoles TCP et UDP ainsi que l'échange de structures de donnés
et la prise en charge du réseau en entier. Testez avec plusieurs clients connectés
pour voir les capacités et la simplicité de la classe.
Je n'ai jamais compilé sous Linux mais je ne pense pas que cela marche.
Source / Exemple :
/* Exemple de code utilisant TIM_Reseau coté serveur
Auteur : Williamallas de Total_Immersion */
#include <iostream>
#include "TIM_Reseau\TIM_Server.h" // header de la classe TIM_Reseau
#define CLIENT_MAX 8
#define PORT_TCP 54000
#define PORT_UDP 54001
#define ID_TYPE_PROFILE 1 // c'est l'id du type contenant la structure Profile,
// l'id doit être le même pour le serveur et tous les clients
#define ID_TYPE_TEXT 2
struct Profile // structure contenant le profile d'un client
{
char pseudo[25];
int age;
};
struct Text // structure contenent un message d'un client
{
char txt[200];
int protocole; // 1 = TCP, 2 = UDP
};
using namespace std;
/* Prototypes des fonctions */
void toutInit(TIM_Server & serveur); // initialise le protocole TCP et UDP
void gestionMessage(TIM_Server & serveur, int id); // récupère et affiche les messages
int main()
{
TIM_Server serveur;
int err;
toutInit(serveur); // // initialise le protocole TCP et UDP
serveur.createNewType(ID_TYPE_PROFILE, 50, sizeof(Profile)); // on crée un type pour les structures Profile
serveur.createNewType(ID_TYPE_TEXT, 50, sizeof(Text)); // on crée un type pour les structures Text
err = serveur.startListen(PORT_TCP); // on écoute sur le port 54000 et on attend les connections
if(err != OK){
cout << "startListen() : " << serveur.printError(err) << endl; // on affiche l'erreur
system("pause"); exit(0);
}
err = serveur.startRecvUdp(PORT_UDP); // on écoute sur le port 54001 par le protocole UDP
if(err != OK){
cout << "startRecvUdp() : " << serveur.printError(err) << endl; // on affiche l'erreur
system("pause"); exit(0);
}
cout << "Lancemenet du serveur reussie !" << endl << endl;
bool continu = true;
int what, id;
while(continu) // la boucle d'attente des évenements
{
err = serveur.waitNewEvent(what, id, INFINITY); // on attend un évenement pendant un temps infinie
if(err != OK)
cout << serveur.printError(err) << endl; // si une erreur s'est produite on l'affiche
else // sinon on traite l'évenement
{
Client_Info info; // servant à récupérer les informations d'un client
switch(what) // l'évenement est identifié par la variable what
{
case CONNECTION: // un nouveau client s'est connecté
serveur.getClientInfo(id, info); // on demande les informations sur ce client, on utilise la structure Client_Info
cout << "Le client d'id " << id << " s'est connecte." << endl;
cout << "Informations : " << info.ip << ":" << info.port << endl; // on affiche les informations du client
break;
case DECONNECTION: // un client s'est déconnecté
cout << "Le client d'id " << id << " s'est deconnecte." << endl;
break;
case MESSAGE: // un nouveau message est arrivé, id contient l'id du type du message
gestionMessage(serveur, id); // récupère et affiche les messages
break;
}
}
cout << endl;
}
return 0;
}
void toutInit(TIM_Server & serveur)
{
if(serveur.init(CLIENT_MAX, true) == OK) // on initilise le module TCP en autorisant les échanges client-client
cout << "Initialisation de TCP reussie" << endl;
else{
cout << "Erreur initialisation de TCP" << endl;
system("pause");
exit(0);
}
if(serveur.initUdp() == OK) // on initilise le module UDP
cout << "Initialisation de UDP reussie" << endl;
else{
cout << "Erreur initialisation de UDP" << endl;
system("pause");
exit(0);
}
}
void gestionMessage(TIM_Server & serveur, int id) // récupère et affiche les messages
{
int idClient, err;
Profile profile; // pour recevoir le profile des nouveaux clients
Text txt; // pour recevoir les messages de type Text
if(id == ID_TYPE_PROFILE) // si le message appartient au type Profile
{
err = serveur.recvRecentMessage(profile, id, &idClient); //on recupère le message
if(err == OK) // si il n'y a pas d'erreur lors de la récupération du message
{
cout << "Profile du client d'id " << idClient << endl;
cout << "Pseudo : " << profile.pseudo << " Age : " << profile.age << endl; // on affiche le profile du client
}
else // il y a une erreur
{
cout << "Impossible de recuperer le profile du client : " << serveur.printError(err) << endl;
}
}
else if(id == ID_TYPE_TEXT) // le message appartient au type Text
{
err = serveur.recvRecentMessage(txt, id, &idClient); //on recupère le message
if(err == OK) // si il n'y a pas d'erreur lors de la récupération du message
{
if(txt.protocole == 2) // le message est arrivé par la voie TCP
cout << "Le client d'id " << idClient << " ecrit par UDP : " << txt.txt << endl;
else // le message est arrivé par la voie UDP
cout << "Le client d'id " << idClient << " ecrit par TCP : " << txt.txt << endl;
}
else // il y a une erreur
{
cout << "Impossible de recuperer le message du client : " << serveur.printError(err) << endl;
}
}
}
Conclusion :
Pour conclure, cette classe est utilisable dans presque toutes les situations, à
utiliser si vous ne voulez pas développer entièrement la partie réseau de votre
projet.
Si vous réussissez à adapter la librairie pour Linux vous pouvez m'envoyer le code
à l'adresse mentionnée à la fin de Doc TIM_Reseau.txt.
Si vous avez des questions n'hésitez pas.
Merci de me laisser vos commentaires et vos découvertes de bug.
Bon code !
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.