Pourquoi Go est le langage idéal pour la programmation réseau ?
\n\nSi vous avez déjà écrit un serveur réseau en Python (notamment avec socket ou asyncio), vous savez à quelle vitesse le code peut se transformer en un labyrinthe de callbacks et de boucles d'événements. Go (Golang) résout ce problème au niveau architectural : les goroutines et les canaux rendent le travail asynchrone avec le réseau aussi simple que l'écriture de code séquentiel.
Dans cet article, nous allons explorer la programmation réseau en Go de manière pratique. Vous apprendrez à créer un chat TCP complet en 15 minutes, envoyer un paquet UDP et lancer un serveur HTTP avec routage. Tous les exemples sont fonctionnels et prêts à être copiés et exécutés.
\n\nLes bases : le package net et sa superpuissance
\n\nEn Go, toute la magie réseau réside dans le package standard net. Il offre une interface unifiée pour travailler avec TCP, UDP, les sockets Unix et même SSL/TLS. L'atout principal : les fonctions Listen, Dial et Accept fonctionnent de manière synchrone, mais sans bloquer tout le programme, car chaque goroutine est légère.
Passons directement à la pratique.
\n\nServeur TCP : un chat en 10 lignes
\n\nCréons un simple serveur echo qui accepte les connexions et renvoie ce qu'il reçoit. C'est un classique de la programmation réseau en Go.
\n\npackage main\n\nimport (\n "bufio"\n "fmt"\n "net"\n)\n\nfunc handleConnection(conn net.Conn) {\n defer conn.Close()\n scanner := bufio.NewScanner(conn)\n for scanner.Scan() {\n message := scanner.Text()\n fmt.Printf("Reçu : %s\\n", message)\n conn.Write([]byte("Echo : " + message + "\\n"))\n }\n}\n\nfunc main() {\n listener, _ := net.Listen("tcp", ":8080")\n fmt.Println("Serveur TCP démarré sur le port :8080")\n for {\n conn, _ := listener.Accept()\n go handleConnection(conn) // chaque goroutine = un client distinct\n }\n}\n\nQue se passe-t-il ici ?
\n- \n
net.Listen("tcp", ":8080")crée un écouteur TCP sur le port 8080. \n - La boucle infinie
foraccepte les nouvelles connexions viaAccept(). \n - Chaque connexion est traitée dans une goroutine séparée
go handleConnection(). \n - Dans la fonction, nous lisons les lignes avec
bufio.Scanneret envoyons une réponse. \n
Exécutez ce code, ouvrez un terminal et connectez-vous avec nc localhost 8080 (ou Putty). Tout message sera renvoyé avec le préfixe "Echo :". Étonnamment, c'est déjà un serveur réseau complet, capable de gérer des milliers de clients sans aucun callback.
UDP : livraison rapide sans garantie
\n\nSi TCP ressemble à une conversation téléphonique (connexion établie, on dialogue), UDP est comme une carte postale : on envoie et on oublie. Go rend le travail avec UDP tout aussi simple.
\n\nClient et serveur UDP
\n\n// Serveur\npackage main\n\nimport (\n "fmt"\n "net"\n)\n\nfunc main() {\n addr, _ := net.ResolveUDPAddr("udp", ":8081")\n conn, _ := net.ListenUDP("udp", addr)\n defer conn.Close()\n\n buffer := make([]byte, 1024)\n for {\n n, clientAddr, _ := conn.ReadFromUDP(buffer)\n message := string(buffer[:n])\n fmt.Printf("Reçu de %s : %s\\n", clientAddr, message)\n conn.WriteToUDP([]byte("Accepté : "+message+"\\n"), clientAddr)\n }\n}\n\n// Client\n// Dans un fichier séparé ou une goroutine :\nconn, _ := net.Dial("udp", "localhost:8081")\ndefer conn.Close()\nconn.Write([]byte("Bonjour, UDP !"))\nbuffer := make([]byte, 1024)\nn, _ := conn.Read(buffer)\nfmt.Println(string(buffer[:n]))\n\nDifférence clé avec TCP :
\n- \n
- Pas de
Accept()— on écoute simplement le port et on lit les datagrammes. \n - Chaque paquet arrive avec l'adresse de l'expéditeur. \n
- Go gère lui-même la mise en mémoire tampon :
ReadFromUDPlit un paquet à la fois. \n