Skip to content

net

La biblioteca estándar net de Go es muy poderosa. Proporciona funciones para manejar tareas comunes como comunicación de red, direcciones IP, resolución DNS, protocolos TCP/UDP, protocolo HTTP, etc. Debido a las características de concurrencia del lenguaje Go, el manejo de E/S de red es muy conciso y eficiente.

Análisis de direcciones

Go proporciona cuatro funciones para analizar direcciones de red. A continuación se explican una por una.

Dirección MAC

Firma

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

Ejemplo

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)

Ejemplo

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

Dirección IP

La dirección IP admite el análisis de ipv4 e ipv6. La firma de la función es la siguiente

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

El ejemplo de uso es el siguiente

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

Dirección TCP

La dirección TCP admite tcp4 y tcp6. La firma es la siguiente

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

El ejemplo de uso es el siguiente

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

Dirección UDP

La dirección UDP admite udp4 y udp6. La firma es la siguiente

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

El ejemplo de uso es el siguiente

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

Dirección Unix

La dirección Unix admite unix, unixgram y unixpacket. La firma es la siguiente

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

El ejemplo de uso es el siguiente

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 también proporciona muchas funciones para consultas DNS. A continuación se muestra un ejemplo de análisis de la dirección IP de un nombre de dominio

go
package main

import (
  "fmt"
  "net"
)

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

Consultar valores de registro MX

go
package main

import (
  "fmt"
  "net"
)

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

Programación de red

La lógica de programación TCP es muy simple. Para el cliente es

  1. Establecer conexión
  2. Enviar datos o leer datos
  3. Salir

Para el servidor es

  1. Escuchar dirección
  2. Obtener conexión
  3. Crear una nueva goroutine para manejar la conexión

A continuación se muestra un ejemplo simple, código del cliente

go
package main

import (
  "net"
)

func main() {
  // Establecer conexión
  conn, err := net.Dial("tcp", "0.0.0.0:1234")
  if err != nil {
    panic(err)
  }
  defer conn.Close()

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

Código del servidor

go
package main

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

func main() {
  // Escuchar dirección
  listener, err := net.Listen("tcp", "0.0.0.0:1234")
  if err != nil {
    panic(err)
  }
  defer listener.Close()

  var wg sync.WaitGroup

  for {
    // Bloquear esperando que se establezca la siguiente conexión
    conn, err := listener.Accept()
    if err != nil {
      panic(err)
    }

    // Iniciar una nueva goroutine para manejar la conexión de forma asíncrona
    wg.Add(1)
    go func() {
      defer wg.Done()
      buf := make([]byte, 4096)
      for {
        // Leer datos de la conexión
        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()
}

El cliente envía datos y el servidor recibe datos. Este ejemplo es muy simple. Cuando el servidor establece una nueva conexión, solo necesita iniciar una nueva goroutine para manejarla sin bloquear. La escritura de UDP es generalmente similar.

Golang editado por www.golangdev.cn