Skip to content

net

La libreria standard net di Go è molto potente, fornisce funzionalità per gestire comunicazioni di rete, indirizzi IP, risoluzione DNS, protocolli TCP/UDP, protocollo HTTP e altri compiti comuni. Grazie alle caratteristiche di concorrenza del linguaggio Go stesso, la gestione dell'IO di rete è molto concisa ed efficiente.

Risoluzione Indirizzi

Go fornisce quattro funzioni per analizzare indirizzi di rete, di seguito verranno spiegate una per una.

Indirizzo MAC

Firma

go
func ParseMAC(s string) (hw HardwareAddr, err error)

Esempio

go
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

Firma

go
func ParseCIDR(s string) (IP, *IPNet, error)

Esempio

go
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)
}

Indirizzo IP

L'indirizzo IP supporta l'analisi di ipv4 e ipv6, la firma della funzione è la seguente

go
func ResolveIPAddr(network, address string) (*IPAddr, error)

Esempio di utilizzo

go
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)
}

Indirizzo TCP

L'indirizzo TCP supporta tcp4 e tcp6, la firma è la seguente

go
func ResolveTCPAddr(network, address string) (*TCPAddr, error)

Esempio di utilizzo

go
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)
}

Indirizzo UDP

L'indirizzo UDP supporta udp4 e udp6, la firma è la seguente

go
func ResolveUDPAddr(network, address string) (*UDPAddr, error)

Esempio di utilizzo

go
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)
}

Indirizzo Unix

L'indirizzo Unix supporta unix, unixgram, unixpacket, la firma è la seguente

go
func ResolveUnixAddr(network, address string) (*UnixAddr, error)

Esempio di utilizzo

go
package main

import (
    "fmt"
    "net"
)

func main() {
    unixAddr, err := net.ResolveUnixAddr("unix", "/tmp/mysocket")
    if err != nil {
       panic(err)
    }
    fmt.Println(unixAddr)
}

DNS

Go fornisce anche molte funzioni per le query DNS, di seguito un esempio per analizzare l'indirizzo IP di un dominio

go
package main

import (
  "fmt"
  "net"
)

func main() {
  addrs, err := net.LookupHost("github.com")
  if err != nil {
    panic(err)
  }
  fmt.Println(addrs)
}

Interrogazione del record MX

go
package main

import (
  "fmt"
  "net"
)

func main() {
  mxs, err := net.LookupMX("github.com")
  if err != nil {
    panic(err)
  }
  fmt.Println(mxs)
}

Programmazione di Rete

La logica della programmazione tcp è molto semplice, per il client è

  1. Stabilire una connessione
  2. Inviare dati o leggere dati
  3. Uscire

Per il server è

  1. Ascoltare un indirizzo
  2. Ottenere la connessione
  3. Creare una nuova goroutine per gestire la connessione

Di seguito un esempio semplice, codice client

go
package main

import (
  "net"
)

func main() {
  // Stabilire una connessione
  conn, err := net.Dial("tcp", "0.0.0.0:1234")
  if err != nil {
    panic(err)
  }
  defer conn.Close()

  // Inviare dati
  for i := range 10 {
    _, err := conn.Write([]byte{'a' + byte(i)})
    if err != nil {
      panic(err)
    }
  }
}

Codice server

go
package main

import (
  "errors"
  "fmt"
  "io"
  "net"
  "sync"
)

func main() {
  // Ascoltare un indirizzo
  listener, err := net.Listen("tcp", "0.0.0.0:1234")
  if err != nil {
    panic(err)
  }
  defer listener.Close()

  var wg sync.WaitGroup

  for {
    // Bloccare in attesa che la prossima connessione venga stabilita
    conn, err := listener.Accept()
    if err != nil {
      panic(err)
    }

    // Avviare una nuova goroutine per gestire la connessione in modo asincrono
    wg.Add(1)
    go func() {
      defer wg.Done()
      buf := make([]byte, 4096)
      for {
        // Leggere dati dalla connessione
        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()
}

Il client invia dati, il server riceve dati, questo esempio è molto semplice, quando il server stabilisce una nuova connessione, basta avviare una nuova goroutine per gestirla, senza bloccare. La scrittura per UDP è fondamentalmente simile.

Golang by www.golangdev.cn edit