Skip to content

net

Go 언어의 net 표준 라이브러리는 매우 강력한 라이브러리로, 네트워크 통신, IP 주소, DNS 해석, TCP/UDP 프로토콜, HTTP 프로토콜 등 일반적인 작업 처리 기능을 제공합니다. Go 언어 자체의 동시성 특성 덕분에 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. 해당 연결을 처리할 새 고루틴 생성

아래는 간단한 예시입니다. 클라이언트 코드

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

    // 새 고루틴을 시작하여 해당 연결을 비동기로 처리
    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()
}

클라이언트가 데이터를 전송하고 서버가 데이터를 수신합니다. 이 예시는 매우 간단합니다. 서버는 새 연결을 설정할 때 새 고루틴을 시작하여 처리하면 되며 블로킹할 필요가 없습니다. UDP 도 대체로 유사하게 작성합니다.

Golang by www.golangdev.cn edit