UDP
特点
- 无连接:只知道对端的IP和端口号就可以发送,不需要实现建立连接。
- 不可靠:没有确认机制, 没有重传机制。如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息。
- 面向数据报: 应用层交给UDP多长的报文, UDP原样发送既不会拆分,也不会合并。如果发送端调用一次sendto, 发送100个字节, 那么接收端也必须调用对应的一次recvfrom, 接收100个 字节,而不能循环调用10次recvfrom, 每次接收10个字节。所以UDP不能够灵活的控制读写数据的次数和数量。
- UDP存在接收缓冲区,但不存在发送缓冲区。
协议
https://zhuanlan.zhihu.com/p/357080855
服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package main
import ( "fmt" "net" )
func main() { udp, err := net.ListenUDP("udp", &net.UDPAddr{ IP: net.IPv4(0, 0, 0, 0), Port: 9999, }) if err != nil { fmt.Println(err) return } defer udp.Close() for { var revfromclient [1024]byte n, addr, err := udp.ReadFromUDP(revfromclient[:]) if err != nil { fmt.Println(err) return } fmt.Printf("%s client send: %s \n", addr, string(revfromclient[:n])) udp.WriteTo([]byte("OK\r"), addr) } }
|
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| package main
import ( "bufio" "fmt" "net" "os" )
func main() {
dial, err := net.Dial("udp", "0.0.0.0:9999")
if err != nil { fmt.Println("网络错误") return
}
defer dial.Close()
input := bufio.NewReader(os.Stdin)
for { s, _ := input.ReadString('\n') _, err = dial.Write([]byte(s)) if err != nil { fmt.Println("发送数据失败") return } }
var b [1024]byte
n, err := dial.Read(b[:])
if err != nil { fmt.Println("接收数据失败") return } fmt.Println("接收的消息:", string(b[:n]))
}
|