Skip to content

net

حزمة net القياسية في لغة Go هي مكتبة قوية جداً، فهي توفر وظائف للتعامل مع الاتصالات الشبكية، وعناوين IP، وتحليل DNS، وبروتوكولات TCP/UDP، وبروتوكول HTTP والمهام الشائعة الأخرى. وبسبب خصائص التزامن الأصلي في لغة Go، فإن التعامل مع الإدخال/الإخراج الشبكي في Go بسيط وفعال جداً.

تحليل العناوين

توفر 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 تم تحريره بواسطة www.golangdev.cn