net
Le package standard net de Go est une bibliothèque très puissante. Il fournit des fonctionnalités pour gérer les communications réseau, les adresses IP, la résolution DNS, les protocoles TCP/UDP, le protocole HTTP et d'autres tâches courantes. Grâce aux caractéristiques concurrentes natives de Go, le traitement des E/S réseau en Go est très concis et efficace.
Résolution d'adresses
Go fournit quatre fonctions pour résoudre les adresses réseau, expliquées ci-dessous une par une.
Adresse MAC
Signature
func ParseMAC(s string) (hw HardwareAddr, err error)Exemple
package main
import (
"fmt"
"net"
)
func main() {
hw, err := net.ParseMAC("00:1A:2B:3C:4D:5E")
if err != nil {
panic(err)
}
fmt.Println(hw)
}CIDR
Signature
func ParseCIDR(s string) (IP, *IPNet, error)Exemple
package main
import (
"fmt"
"log"
"net"
)
func main() {
ipv4Addr, ipv4Net, err := net.ParseCIDR("192.0.2.1/24")
if err != nil {
log.Fatal(err)
}
fmt.Println(ipv4Addr)
fmt.Println(ipv4Net)
}Adresse IP
La résolution d'adresses IP supporte ipv4 et ipv6, la signature de la fonction est la suivante
func ResolveIPAddr(network, address string) (*IPAddr, error)Exemple d'utilisation
package main
import (
"fmt"
"net"
)
func main() {
ipv4Addr, err := net.ResolveIPAddr("ip4", "192.168.2.1")
if err != nil {
panic(err)
}
fmt.Println(ipv4Addr)
ipv6Addr, err := net.ResolveIPAddr("ip6", "2001:0db8:85a3:0000:0000:8a2e:0370:7334")
if err != nil {
panic(err)
}
fmt.Println(ipv6Addr)
}Adresse TCP
L'adresse TCP supporte tcp4 et tcp6, la signature est la suivante
func ResolveTCPAddr(network, address string) (*TCPAddr, error)Exemple d'utilisation
package main
import (
"fmt"
"net"
)
func main() {
tcp4Addr, err := net.ResolveTCPAddr("tcp4", "0.0.0.0:2020")
if err != nil {
panic(err)
}
fmt.Println(tcp4Addr)
tcp6Addr, err := net.ResolveTCPAddr("tcp6", "[::1]:8080")
if err != nil {
panic(err)
}
fmt.Println(tcp6Addr)
}Adresse UDP
L'adresse UDP supporte udp4 et udp6, la signature est la suivante
func ResolveUDPAddr(network, address string) (*UDPAddr, error)Exemple d'utilisation
package main
import (
"fmt"
"net"
)
func main() {
udp4Addr, err := net.ResolveUDPAddr("udp4", "0.0.0.0:2020")
if err != nil {
panic(err)
}
fmt.Println(udp4Addr)
udp6Addr, err := net.ResolveUDPAddr("udp6", "[::1]:8080")
if err != nil {
panic(err)
}
fmt.Println(udp6Addr)
}Adresse Unix
L'adresse Unix supporte unix, unixgram, unixpacket, la signature est la suivante
func ResolveUnixAddr(network, address string) (*UnixAddr, error)Exemple d'utilisation
package main
import (
"fmt"
"net"
)
func main() {
unixAddr, err := net.ResolveUnixAddr("unix", "/tmp/mysocket")
if err != nil {
panic(err)
}
fmt.Println(unixAddr)
}DNS
Go fournit également de nombreuses fonctions pour les requêtes DNS. L'exemple suivant montre comment résoudre l'adresse IP d'un nom de domaine
package main
import (
"fmt"
"net"
)
func main() {
addrs, err := net.LookupHost("github.com")
if err != nil {
panic(err)
}
fmt.Println(addrs)
}Requête d'enregistrements
package main
import (
"fmt"
"net"
)
func main() {
mxs, err := net.LookupMX("github.com")
if err != nil {
panic(err)
}
fmt.Println(mxs)
}Programmation réseau
La logique de programmation TCP est très simple. Pour le client, il s'agit de :
- Établir une connexion
- Envoyer ou lire des données
- Quitter
Pour le serveur, il s'agit de :
- Écouter une adresse
- Obtenir une connexion
- Créer une nouvelle goroutine pour traiter cette connexion
Voici un exemple simple, code client
package main
import (
"net"
)
func main() {
// Établir une connexion
conn, err := net.Dial("tcp", "0.0.0.0:1234")
if err != nil {
panic(err)
}
defer conn.Close()
// Envoyer des données
for i := range 10 {
_, err := conn.Write([]byte{'a' + byte(i)})
if err != nil {
panic(err)
}
}
}Code serveur
package main
import (
"errors"
"fmt"
"io"
"net"
"sync"
)
func main() {
// Écouter l'adresse
listener, err := net.Listen("tcp", "0.0.0.0:1234")
if err != nil {
panic(err)
}
defer listener.Close()
var wg sync.WaitGroup
for {
// Attendre bloquant la prochaine connexion
conn, err := listener.Accept()
if err != nil {
panic(err)
}
// Démarrer une nouvelle goroutine pour traiter cette connexion de manière asynchrone
wg.Add(1)
go func() {
defer wg.Done()
buf := make([]byte, 4096)
for {
// Lire les données depuis la connexion
n, err := conn.Read(buf)
if errors.Is(err, io.EOF) {
break
} else if err != nil {
panic(err)
}
data := string(buf[:n])
fmt.Println(data)
}
}()
}
wg.Wait()
}Le client envoie des données, le serveur les reçoit. Cet exemple est très simple. Lorsqu'une nouvelle connexion est établie sur le serveur, il suffit de démarrer une nouvelle goroutine pour la traiter sans bloquer. L'écriture UDP est globalement similaire.
