> For the complete documentation index, see [llms.txt](https://wskdsgcf.gitbook.io/mastering-go-zh-cn/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wskdsgcf.gitbook.io/mastering-go-zh-cn/13.0/13.4.md).

# 13.4 UDP 客户端

如果您知道怎么开放一个 TCP 客户端，那么由于 UDP 协议的简单性，对于您来说开发一个 UDP 客户端应该更简单。

> *UDP 和 TCP 最大的不同是 UDP 的不可靠性。这也意味着，UDP 要比 TCP 简单，因为 UDP 不需要保持一个 UDP 连接的状态。*

展现这个主题的工具命名为 UDPclient.go，它分成四个代码片段。 UDPclient.go 的第一段如下：

```go
package main

import(
    "bufio"
    "fmt"
    "net"
    "os"
    "strings"
)
```

UDPclient.go 的第二段如下：

```go
func main() {
    arguments := os.Args
    if len(arguments) == 1 {
        fmt.Println("Please provide a host:post string")
        return
    } 
    CONNECT := arguments[1]
    s, err := net.ResolveUDPAddr("udp4", CONNECT)
    c, err := net.DialUDP("udp4", nil, s)

    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Printf("The UDP server is %s\n", c.RemoteAddr().String())
    defer c.Close()
```

net.ResolveUDPAddr() 函数返回一个由第二个参数定义的 UDP 终点地址。第一个参数（`udp4`）规定了程序只能支持 IPv4 协议。

net.DialUDP() 函数相当于 net.Dial() 对 UDP 网络。

UDPclient.go 的第三段代码如下：

```go
    for {
        reader := bufio.NewReader(os.Stdin)
        fmt.Print(">> ")
        text, _ := reader.ReadString("\n")
        data := []byte(text + "\n")
        _, err = c.Write(data)
        if strings.TrimSpace(string(data)) == "STOP" {
            fmt.Println("Exiting UDP client!")
            return
        }
```

上面这段代码需要使用者输入一些文本，发送给 UDP 服务器。使用 `buio.NewReader(os.Stdin)` 从标准输入中读取输入的文本。`Write(data)` 方法通过 UDP 网络连接发送数据。

剩下的代码如下：

```go
        if err != nil {
            fmt.Println(err)
            return
        }

        buffer := make([]byte, 1024)
        n, _, err := c.ReadFromUDP(buffer)
        if err != nil {
            fmt.Println(err)
            return
        }
        fmt.Printf("Reply: %s\n", string(buffer[0:n]))
    }
}
```

一旦客户端数据被发送出去后， 您必须等待 UDP 服务器发送的数据，使用 `ReadFromUDP()` 读取。

执行 `UDPclient.go` 并使用 `netcat(l)` 工具作为 UDP 服务器与之交互，将产生如下输出：

```
$ go run UDPclient.go localhost:8001
The UDP server is 127.0.0.1:8001
>> Hello!
Reply: Hi there!

>> Have to leave - bye!
Reply: OK.

>> STOP
Exiting UDP client!
```

在 UDP 服务器这边，输出如下：

```
$ nc -v -u -l 127.0.0.0 8001
Hello!

Hi there!
Have to leave - bye!

OK.
STOP

^C
```

因为当 `nc(l)` 收到输入的`STOP` 字符串时，没有任何代码能告诉它终止，所以键入 `Control + C` 去停止它。
