net
ไลบรารีมาตรฐาน net ของภาษา Go เป็นไลบรารีที่ทรงพลังมาก จัดเตรียมฟังก์ชันสำหรับจัดการการสื่อสารเครือข่าย ที่อยู่ IP การแยกวิเคราะห์ DNS โปรโตคอล TCP/UDP โปรโตคอล HTTP และงานทั่วไปอื่นๆ เนื่องจากคุณสมบัติพร้อมกันของภาษา Go ทำให้การประมวลผลเครือข่าย IO มีประสิทธิภาพและรวดเร็ว
การแยกวิเคราะห์ที่อยู่
Go จัดเตรียมฟังก์ชันสี่ฟังก์ชันสำหรับการแยกวิเคราะห์ที่อยู่เครือข่าย จะอธิบายทีละฟังก์ชันด้านล่าง
ที่อยู่ MAC
ลายเซ็น
func ParseMAC(s string) (hw HardwareAddr, err error)ตัวอย่าง
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
ลายเซ็น
func ParseCIDR(s string) (IP, *IPNet, error)ตัวอย่าง
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 ลายเซ็นฟังก์ชันดังนี้
func ResolveIPAddr(network, address string) (*IPAddr, error)ตัวอย่างการใช้งานดังนี้
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 ลายเซ็นดังนี้
func ResolveTCPAddr(network, address string) (*TCPAddr, error)ตัวอย่างการใช้งานดังนี้
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 ลายเซ็นดังนี้
func ResolveUDPAddr(network, address string) (*UDPAddr, error)ตัวอย่างการใช้งานดังนี้
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 ลายเซ็นดังนี้
func ResolveUnixAddr(network, address string) (*UnixAddr, error)ตัวอย่างการใช้งานดังนี้
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 ของโดเมน
package main
import (
"fmt"
"net"
)
func main() {
addrs, err := net.LookupHost("github.com")
if err != nil {
panic(err)
}
fmt.Println(addrs)
}查询记录值
package main
import (
"fmt"
"net"
)
func main() {
mxs, err := net.LookupMX("github.com")
if err != nil {
panic(err)
}
fmt.Println(mxs)
}การเขียนโปรแกรมเครือข่าย
ตรรกะการเขียนโปรแกรม tcp ง่ายมาก สำหรับไคลเอนต์คือ
- สร้างการเชื่อมต่อ
- ส่งข้อมูลหรืออ่านข้อมูล
- ออก
สำหรับเซิร์ฟเวอร์คือ
- ฟังที่อยู่
- รับการเชื่อมต่อ
- สร้าง goroutine ใหม่เพื่อจัดการการเชื่อมต่อนั้น
ด้านล่างนี้เป็นตัวอย่างง่าย โค้ดไคลเอนต์
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)
}
}
}โค้ดเซิร์ฟเวอร์
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 โดยทั่วไปก็เขียนคล้ายกัน
