Skip to content

net

ไลบรารีมาตรฐาน net ของภาษา Go เป็นไลบรารีที่ทรงพลังมาก จัดเตรียมฟังก์ชันสำหรับจัดการการสื่อสารเครือข่าย ที่อยู่ IP การแยกวิเคราะห์ DNS โปรโตคอล TCP/UDP โปรโตคอล HTTP และงานทั่วไปอื่นๆ เนื่องจากคุณสมบัติพร้อมกันของภาษา Go ทำให้การประมวลผลเครือข่าย IO มีประสิทธิภาพและรวดเร็ว

การแยกวิเคราะห์ที่อยู่

Go จัดเตรียมฟังก์ชันสี่ฟังก์ชันสำหรับการแยกวิเคราะห์ที่อยู่เครือข่าย จะอธิบายทีละฟังก์ชันด้านล่าง

ที่อยู่ MAC

ลายเซ็น

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

ตัวอย่าง

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

ลายเซ็น

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

ตัวอย่าง

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

ที่อยู่ IP

ที่อยู่ IP รองรับ ipv4, ipv6 ลายเซ็นฟังก์ชันดังนี้

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

ตัวอย่างการใช้งานดังนี้

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

ที่อยู่ TCP

ที่อยู่ TCP รองรับ tcp4, tcp6 ลายเซ็นดังนี้

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

ตัวอย่างการใช้งานดังนี้

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

ที่อยู่ UDP

ที่อยู่ UDP รองรับ udp4, udp6 ลายเซ็นดังนี้

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

ตัวอย่างการใช้งานดังนี้

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

ที่อยู่ Unix

ที่อยู่ Unix รองรับ unix, unixgram, unixpacket ลายเซ็นดังนี้

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

ตัวอย่างการใช้งานดังนี้

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 ยังจัดเตรียมฟังก์ชันมากมายสำหรับการค้นหา DNS ด้านล่างนี้เป็นตัวอย่างการแยกวิเคราะห์ที่อยู่ IP ของโดเมน

go
package main

import (
  "fmt"
  "net"
)

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

查询记录值

go
package main

import (
  "fmt"
  "net"
)

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

การเขียนโปรแกรมเครือข่าย

ตรรกะการเขียนโปรแกรม tcp ง่ายมาก สำหรับไคลเอนต์คือ

  1. สร้างการเชื่อมต่อ
  2. ส่งข้อมูลหรืออ่านข้อมูล
  3. ออก

สำหรับเซิร์ฟเวอร์คือ

  1. ฟังที่อยู่
  2. รับการเชื่อมต่อ
  3. สร้าง goroutine ใหม่เพื่อจัดการการเชื่อมต่อนั้น

ด้านล่างนี้เป็นตัวอย่างง่าย โค้ดไคลเอนต์

go
package main

import (
  "net"
)

func main() {
  // สร้างการเชื่อมต่อ
  conn, err := net.Dial("tcp", "0.0.0.0:1234")
  if err != nil {
    panic(err)
  }
  defer conn.Close()

  // ส่งข้อมูล
  for i := range 10 {
    _, err := conn.Write([]byte{'a' + byte(i)})
    if err != nil {
      panic(err)
    }
  }
}

โค้ดเซิร์ฟเวอร์

go
package main

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

func main() {
  // ฟังที่อยู่
  listener, err := net.Listen("tcp", "0.0.0.0:1234")
  if err != nil {
    panic(err)
  }
  defer listener.Close()

  var wg sync.WaitGroup

  for {
    // บล็อกรอการเชื่อมต่อถัดไป
    conn, err := listener.Accept()
    if err != nil {
      panic(err)
    }

    // เปิด goroutine ใหม่เพื่อจัดการการเชื่อมต่อนั้นแบบอะซิงโครนัส
    wg.Add(1)
    go func() {
      defer wg.Done()
      buf := make([]byte, 4096)
      for {
        // อ่านข้อมูลจากการเชื่อมต่อ
        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()
}

ไคลเอนต์ส่งข้อมูล เซิร์ฟเวอร์รับข้อมูล ตัวอย่างนี้ง่ายมาก เมื่อเซิร์ฟเวอร์สร้างการเชื่อมต่อใหม่ เพียงเปิด goroutine ใหม่ก็สามารถจัดการได้ ไม่ต้องบล็อก UDP โดยทั่วไปก็เขียนคล้ายกัน

Golang by www.golangdev.cn edit