Retour aux projets

IRC

C++ Reseau Parsing

Un projet d’école 42 consistant à développer un serveur IRC (Internet Relay Chat) minimaliste en C++. L’objectif est de comprendre le modèle client-serveur, la gestion des sockets et la communication en réseau.

Aperçu du projet IRC

ft_irc

Un projet d’école 42 consistant à développer un serveur IRC (Internet Relay Chat) minimaliste en C++.
L’objectif est de comprendre le modèle client-serveur, la gestion des sockets et la communication en réseau.

Présentation

Le serveur ft_irc implémente un sous-ensemble du protocole IRC :
gestion des connexions, échange de messages, canaux et pseudonymes.
Chaque client se connecte au serveur, rejoint des salons et envoie/reçoit des messages en temps réel.

Concepts clés

Qu’est-ce qu’un socket ?

Un socket est un point de communication bidirectionnel entre deux machines sur un réseau, identifié par une paire (adresse IP : port).
On peut le comparer à un appel téléphonique : le serveur « écoute » sur un numéro, le client « compose » ce numéro pour établir la connexion.

Adresse et port

  • Adresse : IPv4 (e.g. 192.168.0.42) ou IPv6
  • Port : entier 0–65535, identifie un service
  • Ports « réservés » 0–1023 (HTTP : 80, SSH : 22)
  • Ports « dynamiques » 1024–49151

Architecture client-serveur

  1. Le serveur ouvre un socket, se lie à un port, et se met en écoute.
  2. Un client se connecte via ce port.
  3. Le serveur accepte la connexion, crée un nouveau socket dédié au client.
  4. Les deux machines échangent des données (recv/send).
  5. À la déconnexion, on ferme le socket client.

Implémentation pas-à-pas

1. Création du socket

int sock_listen = socket(AF_INET, SOCK_STREAM, 0);
if (sock_listen < 0) {
    std::cerr << "Erreur : échec de la création du socket\n";
    return EXIT_FAILURE;
}
  • AF_INET : famille IPv4
  • SOCK_STREAM : TCP
  • 0 : protocole par défaut (TCP)

2. Configuration (IP & port)

sockaddr_in addr;
addr.sin_family      = AF_INET;
addr.sin_port        = htons(8080);          // port d’écoute
inet_pton(AF_INET, "0.0.0.0", &addr.sin_addr); // toutes interfaces
  • htons() : convertit en réseau (big-endian) (en gros c'est une représentation standard pour les ports)
  • inet_pton() : texte → binaire

3. Bind (liaison)

if (bind(sock_listen, (sockaddr*)&addr, sizeof(addr)) < 0) {
    std::cerr << "Erreur : échec du bind\n";
    return EXIT_FAILURE;
}

Permet de « raccrocher » l’adresse IP/port au socket.

4. Listen (mise en écoute)

if (listen(sock_listen, SOMAXCONN) < 0) {
    std::cerr << "Erreur : échec de l’écoute\n";
    return EXIT_FAILURE;
}
  • SOMAXCONN : nombre maximal de connexions en attente (géré par le système)

5. Accept (acceptation de connexion)

sockaddr_in client_addr;
socklen_t     len = sizeof(client_addr);
int           sock_client = accept(sock_listen,
                                   (sockaddr*)&client_addr,
                                   &len);
if (sock_client < 0) {
    std::cerr << "Erreur : échec de l’accept\n";
    return EXIT_FAILURE;
}

Chaque client obtient un nouveau socket (sock_client) pour la session.

6. Communication (recv/send)

char buffer[4096];
int  bytes;

while ((bytes = recv(sock_client, buffer, sizeof(buffer), 0)) > 0) {
    // Traitement du message reçu
    std::string msg(buffer, bytes);
    std::cout << "Reçu : " << msg << "\n";

    // Echo en réponse
    send(sock_client, buffer, bytes, 0);
}

if (bytes == 0)
    std::cout << "Client déconnecté\n";
else
    std::cerr << "Erreur recv\n";
  • recv() : lit les données du socket
  • send() : envoie des données au socket
  • Le serveur peut traiter les messages reçus et répondre (ici, on fait un echo).

7. Fermeture du socket

close(sock_client);
close(sock_listen);
std::cout << "Serveur arrêté\n";

<!-- divider --!>

/!\ Ici dans cette implementation ne gere que un seul client à la fois.
Normalement on utilise un select() ou un epoll() pour gérer plusieurs clients simultanément.

Bon courage pour la suite !