上卷 程序设计
中卷 标准库
- bufio 1.18
- bytes 1.18
- io 1.18
- container 1.18
- encoding 1.18
- crypto 1.18
- hash 1.18
- index 1.18
- sort 1.18
- context 1.18
- database 1.18
- connection
- query
- queryrow
- exec
- prepare
- transaction
- scan & null
- context
- tcp
- udp
- http
- server
- handler
- client
- h2、tls
- url
- rpc
- exec
- signal
- embed 1.18
- plugin 1.18
- reflect 1.18
- runtime 1.18
- KeepAlived
- ReadMemStats
- SetFinalizer
- Stack
- sync 1.18
- atomic
- mutex
- rwmutex
- waitgroup
- cond
- once
- map
- pool
- copycheck
- nocopy
- unsafe 1.18
- fmt 1.18
- log 1.18
- math 1.18
- time 1.18
- timer
下卷 运行时
源码剖析
附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
udp
用户资料包协议 (UDP)协议是无连接(connectionless)的,不关心后续分组(datagram)状态。
- 协议不可靠,不保证数据报不丢失、不延迟、不错序传输。
- 客户端不关心服务端是否处于监听或者已经准备好接收数据。
- 无连接协议可方便实现一对多,或多对一通信。
实际上作为 TCP、UDP 基础的 IP 协议也是无连接的,TCP 分组(segment)是通过自身来实现可靠性。
多数时候 UDP 要比 TCP 更快。
为便于阅读,示例代码做了精简(未对错误做处理等)。
// server.go package main import ( "log" "net" "runtime" "time" ) const ( network = "udp" address = ":9999" bufsize = 500 timeout = time.Second * 10 ) func server() { ready := make(chan struct{}) go func() { addr, _ := net.ResolveUDPAddr(network, address) conn, _ := net.ListenUDP(network, addr) defer conn.Close() close(ready) // workers sema := make(chan struct{}, runtime.GOMAXPROCS(0)) for { sema <- struct{}{} go func() { defer func(){ <-sema }() handle(conn) }() } }() <-ready } func handle(conn *net.UDPConn) { buf := make([]byte, bufsize) for { conn.SetReadDeadline(time.Now().Add(timeout)) n, addr, err := conn.ReadFromUDP(buf) if n > 0 { conn.WriteToUDP(buf[:n], addr) } if err != nil { if e, ok := err.(net.Error); ok && e.Timeout() { continue } log.Fatalln(err) } } }
// client.go package main import ( "bytes" "fmt" "log" "math/rand" "net" "time" ) func client() { addr, _ := net.ResolveUDPAddr(network, address) conn, _ := net.DialUDP(network, nil, addr) defer conn.Close() sbuf, rbuf := make([]byte, 10), make([]byte, 10) for { // random data. rand.Read(sbuf) // send n, err := conn.Write(sbuf) if err != nil { log.Fatalln(err, n) } // recv n, _, err = conn.ReadFromUDP(rbuf) // verify data. if !bytes.Equal(sbuf, rbuf) { log.Fatalln("sbuf != rbuf") } if n > 0 { fmt.Printf(" > %v, % x\n", conn.LocalAddr(), rbuf[:n]) } if err != nil { log.Fatalln(err) } time.Sleep(time.Millisecond * 50) } }
// main.go package main import ( "log" ) func init() { log.SetFlags(log.Ltime) } func main() { server() for i := 0; i < 10; i++ { go client() } select{} }
数据包
考虑到 UDP 协议的不可靠特性,所以包大小最好限制在 MTU 范围内。
需要减去相关协议头大小。
Internet: MTU(576) - IPv4(20) - UDP(8) = 548 Intranet: MTU(1500) - PPPoE(8) - IPv4(20) - UDP(8) = 1464
鉴于 IP 头最大值是 60,因此建议的 Internet 安全上限为 508 字节。
同理,Intranet 合理阈值 1424 字节。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论