Le modèle client-serveur est un modèle de communication qui divise les tâches entre des ordinateurs spécialisés. Dans ce schéma, un ordinateur agit en tant que serveur pour fournir des ressources ou des services, tandis que d’autres ordinateurs agissent en tant que clients pour demander et recevoir ces ressources ou services.
En C++, la mise en œuvre d’une architecture client-serveur peut être réalisée en utilisant des sockets, qui sont des interfaces de programmation réseau permettant la communication entre les processus s’exécutant sur différents hôtes. Voici quelques exemples d’implémentation de client-serveur en utilisant C++ :
- Serveur TCP simple avec sockets en C++ :
Ce programme crée un serveur TCP simple qui écoute sur un port spécifique et répond aux demandes des clients.
cpp#include
#include
#include
#include
int main() {
int server_socket, client_socket;
struct sockaddr_in server_addr, client_addr;
char buffer[1024] = {0};
const int PORT = 8080;
// Créer un socket
if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Erreur lors de la création du socket");
exit(EXIT_FAILURE);
}
// Initialiser l'adresse du serveur
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
// Lier le socket à l'adresse et au port spécifiés
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Erreur lors du bind");
exit(EXIT_FAILURE);
}
// Mettre le serveur en mode écoute
if (listen(server_socket, 3) < 0) {
perror("Erreur lors de la mise en écoute");
exit(EXIT_FAILURE);
}
std::cout << "Le serveur est en écoute sur le port " << PORT << std::endl;
// Accepter les connexions entrantes
socklen_t client_addr_size = sizeof(client_addr);
if ((client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_size)) < 0) {
perror("Erreur lors de l'acceptation de la connexion");
exit(EXIT_FAILURE);
}
// Lire les données du client et y répondre
read(client_socket, buffer, 1024);
std::cout << "Message du client : " << buffer << std::endl;
const char *message = "Message reçu par le serveur";
send(client_socket, message, strlen(message), 0);
std::cout << "Réponse envoyée au client" << std::endl;
// Fermer les sockets
close(client_socket);
close(server_socket);
return 0;
}
- Client TCP en C++ pour se connecter au serveur :
Ce programme crée un client TCP qui se connecte à un serveur spécifique sur un port donné et envoie un message.
cpp#include
#include
#include
#include
int main() {
int sock = 0;
struct sockaddr_in server_addr;
const char *message = "Bonjour, serveur!";
char buffer[1024] = {0};
const int PORT = 8080;
// Créer un socket
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
std::cerr << "Erreur lors de la création du socket" << std::endl;
return -1;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
// Convertir l'adresse IP en format binaire
if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
std::cerr << "Adresse invalide / non supportée" << std::endl;
return -1;
}
// Connecter le client au serveur
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
std::cerr << "Connexion au serveur échouée" << std::endl;
return -1;
}
// Envoyer un message au serveur
send(sock, message, strlen(message), 0);
std::cout << "Message envoyé au serveur" << std::endl;
// Lire la réponse du serveur
read(sock, buffer, 1024);
std::cout << "Réponse du serveur : " << buffer << std::endl;
// Fermer le socket
close(sock);
return 0;
}
Ces exemples montrent comment créer un simple serveur TCP et un client TCP en C++. Vous pouvez étendre ces exemples pour implémenter des fonctionnalités plus avancées telles que la gestion concurrente des clients, la communication sécurisée via SSL/TLS, ou l’utilisation de protocoles de plus haut niveau comme HTTP.
Plus de connaissances
Bien sûr, voici des informations supplémentaires sur l’architecture client-serveur et sur la façon de la mettre en œuvre en C++ :
Architecture Client-Serveur :
L’architecture client-serveur est un modèle de communication qui divise les tâches entre deux types de programmes :
-
Le serveur : Le serveur est un programme informatique qui fournit des services ou des ressources à d’autres programmes appelés clients. Il attend les demandes des clients, les traite et leur renvoie une réponse.
-
Le client : Le client est un programme qui envoie des demandes au serveur afin d’accéder aux services ou aux ressources qu’il fournit. Il attend ensuite la réponse du serveur pour traiter les résultats.
Dans ce modèle, le serveur fonctionne en permanence et fournit des services à plusieurs clients simultanément. Les clients initient la communication en envoyant une demande au serveur, qui la traite et envoie une réponse.
Implémentation en C++ avec des Sockets :
En C++, la mise en œuvre de l’architecture client-serveur peut se faire en utilisant des sockets, qui sont des interfaces de programmation réseau permettant la communication entre les processus s’exécutant sur différents hôtes. Voici quelques points clés à considérer lors de l’implémentation :
-
Création de sockets : Les sockets sont créés à l’aide de la fonction
socket()
, qui retourne un descripteur de fichier pour le socket nouvellement créé. -
Liaison et écoute : Pour les serveurs, le socket doit être lié à une adresse IP et à un port spécifiques à l’aide de la fonction
bind()
. Ensuite, le serveur doit être mis en mode écoute à l’aide de la fonctionlisten()
pour accepter les connexions entrantes. -
Acceptation des connexions : Une fois en mode écoute, le serveur utilise la fonction
accept()
pour accepter les connexions entrantes des clients. Cette fonction retourne un nouveau descripteur de fichier pour la communication avec ce client spécifique. -
Communication : Une fois qu’une connexion est établie entre le client et le serveur, ils peuvent échanger des données à l’aide des fonctions
send()
etrecv()
pour envoyer et recevoir des données respectivement. -
Fermeture des sockets : Après avoir terminé la communication, les sockets doivent être fermés à l’aide de la fonction
close()
pour libérer les ressources système.
Considérations supplémentaires :
-
Gestion des erreurs : Il est essentiel de gérer les erreurs de manière appropriée lors de la création de sockets, de l’établissement de connexions et de l’envoi/réception de données pour garantir un fonctionnement correct du programme.
-
Sécurité : Pour des applications sensibles à la sécurité, il est recommandé d’utiliser des mécanismes de chiffrement et d’authentification pour protéger la communication entre le client et le serveur, par exemple en utilisant SSL/TLS.
-
Gestion des connexions multiples : Les serveurs doivent être capables de gérer simultanément les connexions de plusieurs clients. Cela peut être réalisé en utilisant des threads ou des processus pour chaque connexion, ou en utilisant des techniques de multiplexage telles que
select()
oupoll()
.
En combinant ces concepts avec des bibliothèques et des frameworks supplémentaires, il est possible de développer des applications client-serveur robustes et extensibles en C++.