golangでUDPを使ってみた

環境情報

go version : 1.8

os : kubuntu 16

やったこと

  1. UDPサーバの実装
  2. UDPクライアントの実装

UDPサーバの実装

UDPはステートレスなプロトコルなので、セッション情報を持たず一方的に送り付けるプロトコルです。 なのでTCPと比べて比較的に実装は楽ですね。(まぁプログラムのコード量自体はそんなに大差ないですが)

UDPで使う主要なメソッド

func net.ResolveUDPAddr(net, addr  string) (*UDPAddr, error)
func net.ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, error)
func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, error)
func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, error)

net.ResolveUDPAddrはTCPと一緒で名前解決してくれるメソッドです。サーバサイドではローカルのIPを指定して待ち受けるポートを指定します。

net.ListenUDPで実際にパケットが来るのを待ち受け状態になります。

ReadFromUDPでパケットが来た場合に内容を読み込み、WriteToUDPで実際にパケットを送ります。

例:

func main() {
    udpAddr, err := net.ResolveUDPAddr("udp", ":1201")
    if err != nil {
        fmt.Fprintf(so.Stderr, "Fatal Error ", err.Error())
        os.Exit(1)
    }

    conn, err := net.ListenUDP("udp", udpAddr)
    if err != nil {
        fmt.Fprintf(so.Stderr, "Fatal Error ", err.Error())
        os.Exit(1)
    }
    
    for {
        handleClient(conn)
    }
}

func handleClient(conn *net.UDPConn) {
    var buf [512]byte

    _, addr, err := conn.ReadFromUDP(buf[0:])
    if err != nil {
        fmt.Fprintf(so.Stderr, "Fataaaaal Error ", err.Error())
        os.Exit(1)
    }
    
    daytime   := time.Now().String()
    conn.WirteToUDP([]byte(daytime), addr)
}

UDPクライアントの実装

クライアントはほとんどサーバと一緒です。違いはクライアント側でリッスンせずに、パケットを送り付けるぐらいですかね。

func net.ResolveUDPAddr(net, addr  string) (*UDPAddr, error)
func net.DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error)

ResolveUDPAddrはサーバと一緒でUDPで送るIPとポートでマッピングを行います。ただサーバと違うのは送りたい先のIPとポートを指定します

DialUDPで実際にパケットを送る先のサーバを設定します

例:

func main() {
    udpAddr, err := net.ResolveUDPAddr("udp", "localhost:1201")
    if err != nil {
        fmt.Fprintf(so.Stderr, "Fataaaaal Error ", err.Error())
        os.Exit(1)
    }

    conn, err != net.DialUDP("udp", nil, udpAddr)
    if err != nil {
        fmt.Fprintf(so.Stderr, "Fataaaaal Error ", err.Error())
        os.Exit(1)
    }

    _, err = conn.Write([]byte("anything")
    if err != nil {
        fmt.Fprintf(so.Stderr, "Fataaaaal Error ", err.Error())
        os.Exit(1)
    }

    var buf [512]byte
    n, err := conn.Read(buf[0:])
    if err != nil {
        fmt.Fprintf(so.Stderr, "Fataaaaal Error ", err.Error())
        os.Exit(1)
    }

    fmt.Println(string(buf[0:n])
}

以上、UDPのサーバとクライアントの実装でした!