Serveur IRC en C++98 conforme à la RFC 1459, où plusieurs clients dialoguent en temps réel via TCP/IP.
Créé le 08/12/2023 · Dernière mise à jour : 17/10/2026
Afficher le sommaire
FT_IRC est un serveur IRC écrit en C++98 d'après la RFC 1459. Il accepte plusieurs clients simultanément sur une seule socket d'écoute et les fait dialoguer par canaux publics ou locaux, messages privés et commandes d'opérateur.
Le serveur ne dépend d'aucune bibliothèque externe, comme l'impose le sujet : l'écoute, l'acceptation des connexions et la lecture des messages reposent uniquement sur les appels système POSIX, orchestrés par select() pour qu'aucun client ne bloque les autres.
Le tout tient dans un seul binaire, ircserv, lancé avec un port et un mot de passe.
| Ressource | Lien |
|---|---|
| Fiche du projet (portfolio) | ZehdBox |
| Catégorie | Technologie | Badge |
|---|---|---|
| Langage | C++98, norme 42 | |
| Réseau | Sockets TCP/IPv4, multiplexage par select() |
|
| Protocole | IRC, RFC 1459 | |
| Compilation | c++, Makefile, sans relink |
|
| Client de test | HexChat, nc |
- Authentification par mot de passe (
PASS) - Pseudonyme et nom d'utilisateur (
NICK,USER) - Canaux publics
#et locaux&(JOIN,PART) - Messages privés et messages de canal (
PRIVMSG) - Opérateurs de canaux :
KICK,INVITE,TOPIC,MODE - Modes de canaux :
+i,+t,+k,+o,+l - Gestion multi-clients non bloquante via
select() - Bonus : bot Pierre-Papier-Ciseaux (
BOT) et compatibilité HexChat (CAP)
Le détail de chaque commande se trouve dans la section Utilisation.
Le serveur ne crée jamais de thread ni de processus : il repose entièrement sur select(), qui lui rend la main dès qu'un descripteur de fichier est prêt, et sur un tampon par client qui recompose les messages arrivés en plusieurs morceaux.
- Vérification des arguments (
checkArgs) : le port et le mot de passe sont validés avant tout appel réseau. - Création du serveur : la socket est créée, attachée au port, mise en écoute, puis inscrite dans un
fd_setparFD_SET. - Boucle principale : à chaque tour,
select()surveille l'ensemble des descripteurs. Le programme ne bloque jamais sur un client en particulier. - Nouvelle connexion :
accept()crée la socket du client, qui rejoint la liste et lefd_set. - Données reçues :
recv()remplit le tampon. Si la ligne n'est pas terminée par\n, le fragment est accumulé pour ce client. Sinon, la commande complète est découpée, puis aiguillée vers son gestionnaire parServer::command. - Déconnexion :
recv()renvoie 0, ou le client envoieQUIT, alors la socket est fermée, retirée dufd_setparFD_CLRet le client est supprimé de la liste. - Arrêt :
SIGINTn'est pas ignoré. Il déclenche une exception qui déroule la pile, libère les ressources et ferme la socket d'écoute.
socket() ──► bind() ──► listen()
│
└──► boucle select()
├── descripteur prêt ──► accept() ──► FD_SET
├── données reçues ──► recv()
│ ├── ligne incomplète ──► bufTmp(PUSH) (tampon par client)
│ └── ligne complète ──► découpage ──► Server::command() ──► réponse
└── connexion fermée ──► close() ──► FD_CLR ──► removeClient()Note
Le tampon par client est ce qui permet de recevoir une commande découpée en plusieurs paquets réseau. C'est ce que vérifie le test « réception de données partielles » plus bas, où com, puis man, puis d finissent par former command.
- Système Unix/Linux (macOS pris en charge)
- Compilateur
c++compatible norme C++98 makencou un client IRC (HexChat, irssi, WeeChat...) pour se connecter
git clone https://github.com/Lamizana/FT_IRC.git
cd FT_IRC
makeNote
Variante SSH : git clone git@github.com:Lamizana/FT_IRC.git
make # règle all- Le Makefile fournit les règles
all,clean,fcleanetre. - Compilation avec
c++et les drapeaux-Wall -Wextra -Werror -std=c++98. - Le Makefile ne relink pas.
make clean # supprime les fichiers objets (.o)
make fclean # supprime les objets + l'exécutable
make re # fclean + all./ircserv <port> <password>- port : numéro de port sur lequel le serveur IRC écoutera les connexions entrantes.
- password : mot de passe de connexion requis pour tout client.
./ircserv 6667 totoAucune bibliothèque externe : le sujet les interdit, Boost compris. Le projet n'utilise que la bibliothèque standard C++98 et les en-têtes système POSIX.
| En-tête | Rôle |
|---|---|
<sys/socket.h> |
socket, bind, listen, accept, recv, send |
<sys/select.h> |
select et fd_set : le multiplexage des descripteurs |
<netinet/in.h> |
Structures d'adresses IPv4 (sockaddr_in) |
<arpa/inet.h> |
Conversions d'adresses |
<unistd.h> |
read, write, close |
<signal.h> |
Interception de SIGINT pour l'arrêt propre |
nc 127.0.0.1 6667
PASS toto
NICK toto
USER toto
JOIN #general- Adresse :
127.0.0.1 - Port :
6667 - Mot de passe :
toto
| Commande | Description |
|---|---|
| CAP | Négociation de capacités (compatibilité client) |
| PASS | Authentification (mot de passe du serveur) |
| NICK | Définir / changer de pseudonyme |
| USER | Définir le nom d'utilisateur (inchangeable) |
| PRIVMSG | Message privé à un utilisateur ou à un canal |
| JOIN | Rejoindre ou créer un canal (#canal) |
| KICK | Éjecter un client d'un canal (opérateur) |
| INVITE | Inviter un client à un canal |
| TOPIC | Modifier ou afficher le thème d'un canal |
| MODE | Changer les modes du canal |
| PART | Quitter un canal |
| BOT | Bonus : jouer à Pierre-Papier-Ciseaux |
| Mode | Description |
|---|---|
| +i / -i | Canal sur invitation uniquement |
| +t / -t | Restreindre TOPIC aux opérateurs |
| +k / -k | Définir / supprimer le mot de passe du canal |
| +o / -o | Donner / retirer le statut d'opérateur |
| +l / -l | Définir / supprimer la limite d'utilisateurs |
Important
- Chaque commande se tape sur UNE SEULE ligne, directement dans la connexion (nc ou client IRC), sans slash (le
/est un raccourci propre aux clients graphiques, pas au protocole brut). - Les commandes sont sensibles à la casse : utilisez uniquement des MAJUSCULES (
PASS,NICK,JOIN...). - Le mot de passe s'envoie sur la même ligne que
PASS:PASS toto(jamaisPASSsur une ligne puistotosur la suivante). - Ordre obligatoire :
PASS→NICK→USER. Le serveur répond alors: 001 <pseudo> :Welcome to the IRC Network.... - Les autres commandes (
JOIN,PRIVMSG,MODE...) ne fonctionnent qu'après ce message de bienvenue.
| Ce que vous tapez | Effet |
|---|---|
PASS toto |
Authentification (doit correspondre au mot de passe de lancement) |
NICK alice |
Définit le pseudonyme (unique, max 9 caractères) |
USER alice |
Définit le nom d'utilisateur (inchangeable ensuite) |
JOIN #general |
Crée ou rejoint le canal #general |
JOIN #securise mdp |
Rejoint un canal protégé par mot de passe |
PRIVMSG #general :salut ! |
Diffuse un message à tout le canal |
PRIVMSG bob :coucou |
Envoie un message privé à bob |
TOPIC #general :Bienvenue |
Modifie le sujet du canal |
TOPIC #general |
Affiche le sujet du canal |
INVITE bob #general |
Invite bob dans le canal |
KICK #general bob :troll |
Éjecte bob (opérateur requis) |
MODE #general +t |
Active un mode du canal (i, t, k, o, l) |
PART #general :a+ |
Quitte le canal |
BOT PAPER |
Bonus : joue à Pierre-Papier-Ciseaux avec le BOT |
./ircserv 6667 toto # Terminal 1 : lancement du serveur
# Terminal 2 : connexion au serveur
nc 127.0.0.1 6667
PASS toto
NICK alice
USER alice
JOIN #general
TOPIC #general :Bienvenue
INVITE bob #general
PRIVMSG #general :salut tout le monde !
PART #generalsudo apt update
sudo apt install hexchathexchat- Fenêtre « Réseaux » : bouton + Add pour créer un réseau.
- Onglet Connexion : cocher « Utiliser un mot de passe » et saisir
toto. - Onglet Utilisateur : définir le pseudo et le nom d'utilisateur.
- Dans « Serveurs », ajouter
127.0.0.1/6667puis cliquer sur Connecter.
/server 127.0.0.1 6667 toto
/join #general/server 127.0.0.1 6667 toto
/join #general
/topic #general Bienvenue
/msg #general salut tout le monde !
/msg alice coucou en privé
/invite alice #general
/kick #general alice troll (opérateur requis)
/part #generalFT_IRC/
├── Makefile # règles all, clean, fclean, re
├── main.cpp # boucle serveur (select) et gestion des connexions
├── define.hpp # numerics et messages IRC
├── library.hpp # bibliothèques et includes communs
├── utils.cpp / utils.hpp # helpers (trim, validation des arguments)
├── Channel/
│ └── Channel.cpp / Channel.hpp # canal : utilisateurs, opérateurs, modes
├── Client/
│ ├── Client.cpp / Client.hpp # client : socket, buffer, enregistrement
│ ├── bot.cpp, invite.cpp, join.cpp, kick.cpp # handlers des commandes
│ ├── mode.cpp, nick.cpp, part.cpp, pass.cpp
│ └── prvmsg.cpp, topic.cpp, user.cpp
└── Server/
├── Server.cpp / Server.hpp # logique serveur et dispatch
├── ServerDebug.cpp # affichage de débogage (<<)
├── ServerMode.cpp # implémentation des modes
├── ServerSwitch.cpp # aiguillage des commandes
└── allClient.cpp # réponses NAMES/ENDOFNAMESOuvrir plusieurs terminaux et se connecter simultanément (nc 127.0.0.1 <port>) pour vérifier la gestion multi-clients.
Envoyer une commande en plusieurs fragments avec nc et Ctrl+D :
$> nc 127.0.0.1 6667
com^Dman^Dd
$>com, puis man, puis d + Entrée reconstruisent la commande transmise au serveur.
Créer un canal, donner +o à un utilisateur, puis tester KICK, TOPIC et MODE.
valgrind --track-origins=yes --leak-check=full --track-fds=yes ./ircserv <port> <password>- PING/PONG non implémenté : les clients IRC se déconnectent après ~60 s d'inactivité (« Ping timeout » dans HexChat).
Projet pédagogique 42 : les corrections et les remarques sont bienvenues via une issue ou une pull request.
Les messages de commit suivent Conventional Commits :
<type>(<scope>): <description>
| Type | Usage |
|---|---|
feat |
Nouvelle fonctionnalité |
fix |
Correction de bug |
docs |
Documentation seule |
refactor |
Réécriture sans changement de comportement |
chore |
Maintenance (configuration, fichiers annexes) |
Scopes : server, client, channel, parsing, readme.
Alex Lamizana, étudiant à 42 Angoulême, spécialisation Data & IA
mvitiell, nminotte : coéquipiers sur le projet.
- 42 Angoulême : cadre pédagogique du projet.
- mvitiell et nminotte : conception et développement du serveur.
Ce projet a été réalisé conformément à la norme de 42.