Skip to content

net

Gói thư viện chuẩn net của Go rất mạnh mẽ, cung cấp các chức năng xử lý truyền thông mạng, địa chỉ IP, phân giải DNS, giao thức TCP/UDP, giao thức HTTP và các tác vụ phổ biến khác. Nhờ đặc tính concurrent của Go, việc xử lý network IO rất gọn nhẹ và hiệu quả.

Phân tích địa chỉ

Go cung cấp bốn hàm để phân tích địa chỉ mạng, dưới đây sẽ giải thích từng cái.

Địa chỉ MAC

Chữ ký

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

Ví dụ

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

Chữ ký

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

Ví dụ

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

Địa chỉ IP

Địa chỉ IP hỗ trợ phân tích ipv4, ipv6, chữ ký hàm như sau

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

Sử dụng ví dụ như sau

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

Địa chỉ TCP

Địa chỉ TCP hỗ trợ tcp4, tcp6, chữ ký như sau

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

Sử dụng ví dụ như sau

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

Địa chỉ UDP

Địa chỉ UDP hỗ trợ udp4, udp6, chữ ký như sau

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

Sử dụng ví dụ như sau

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

Địa chỉ Unix

Địa chỉ Unix hỗ trợ unix, unixgram, unixpacket, chữ ký như sau

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

Sử dụng ví dụ như sau

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 còn cung cấp nhiều hàm dùng cho truy vấn DNS, dưới đây là một ví dụ phân tích địa chỉ IP của tên miền

go
package main

import (
  "fmt"
  "net"
)

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

Truy vấn bản ghi MX

go
package main

import (
  "fmt"
  "net"
)

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

Lập trình mạng

Logic lập trình tcp rất đơn giản, đối với client là

  1. Thiết lập kết nối
  2. Gửi dữ liệu hoặc đọc dữ liệu
  3. Thoát

Đối với server là

  1. Lắng nghe địa chỉ
  2. Lấy kết nối
  3. Tạo một goroutine mới để xử lý kết nối đó

Dưới đây là một ví dụ đơn giản, code client

go
package main

import (
  "net"
)

func main() {
  // Thiết lập kết nối
  conn, err := net.Dial("tcp", "0.0.0.0:1234")
  if err != nil {
    panic(err)
  }
  defer conn.Close()

  // Gửi dữ liệu
  for i := range 10 {
    _, err := conn.Write([]byte{'a' + byte(i)})
    if err != nil {
      panic(err)
    }
  }
}

Code server

go
package main

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

func main() {
  // Lắng nghe địa chỉ
  listener, err := net.Listen("tcp", "0.0.0.0:1234")
  if err != nil {
    panic(err)
  }
  defer listener.Close()

  var wg sync.WaitGroup

  for {
    // Chặn đợi kết nối tiếp theo được thiết lập
    conn, err := listener.Accept()
    if err != nil {
      panic(err)
    }

    // Khởi tạo một goroutine mới để xử lý kết nối đó một cách bất đồng bộ
    wg.Add(1)
    go func() {
      defer wg.Done()
      buf := make([]byte, 4096)
      for {
        // Đọc dữ liệu từ kết nối
        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()
}

Client gửi dữ liệu, server nhận dữ liệu, ví dụ này rất đơn giản, khi server thiết lập kết nối mới, chỉ cần khởi tạo một goroutine mới là có thể xử lý, không cần chặn, UDP về cơ bản cũng viết tương tự.

Golang by www.golangdev.cn edit