golang UDP 协议读取报文问题

2020-02-27 13:30:17 +08:00
 monkeyWie

一次性读满 512 个字节没问题,但是分两次读就读不到了,代码如下

// 读满 512 字节没问题
buf := make([]byte, 512)
_, err =io.ReadFull(r,buf)
// 第一次读没问题
head := make([]byte, 20)
_, err =io.ReadFull(r,head)

// 第二次读一直阻塞
body := make([]byte, 6)
_, err =io.ReadFull(r,body)
7360 次点击
所在节点    Go 编程语言
54 条回复
BBCCBB
2020-02-27 17:33:06 +08:00
话说你这个 io.ReadFull(r, buf) 中的 r 是哪里来的呢.
rio
2020-02-27 17:35:42 +08:00
瞎猜有什么用,UDP 协议基本特性都不知道,回去补习网络基础知识。
monkeyWie
2020-02-27 17:36:58 +08:00
@BBCCBB r 就是一个*net.UDPConn
XiaoxiaoPu
2020-02-27 17:52:09 +08:00
UDP 是面向报文(packet)的协议,一次读取对应一个网络包(packet),不存在一次读取不完或多次读取一个报文。理论上 UDP 报文最大长度是 65507 字节,实际一般不会这么多,要看具体的应用层协议。
BBCCBB
2020-02-27 17:53:20 +08:00
我 google.. 不是调用 UDPConn 的 ReadFromUDP 方法吗.
monkeyWie
2020-02-27 18:00:01 +08:00
@BBCCBB 都一样的,read()底层也是调用的 ReadFrom(),这个 @rio 就是个睿智,说了半天就一直在那秀优越,前面说的也全是错的,真的是 talk is cheap
mightofcode
2020-02-27 18:53:34 +08:00
一次读 1M,绝不会有问题
reus
2020-02-27 19:02:21 +08:00
这个是 ReadFull 的一个局限,它调用 Read 时,如果返回的数据比缓冲区还长,那就会丢弃超出的

所以第二次就读不到了

可以套一个 bufio.Reader,这样超出的部分会缓存起来
tairan2006
2020-02-27 19:22:41 +08:00
udp 一般不都是缓冲区 1024 直接读么…udp 分包特别麻烦,你要用 quic 这种高级一点的协议才行。
whoami9894
2020-02-27 19:46:39 +08:00
@rio #18 你这逻辑,先后次序都颠倒了
rio
2020-02-27 19:48:13 +08:00
@monkeyWie Excuse me? 给你指了方向不去想自己哪里没搞明白,解决问题全靠瞎猜?
rio
2020-02-27 19:50:27 +08:00
@whoami9894 你又想说啥
back0893
2020-02-27 23:22:28 +08:00
我看别人的实现都是初始化一个最大长度的包
直接读取一个包
p2p
2020-02-28 01:03:48 +08:00
buf := make([]byte, 1500)
p2p
2020-02-28 01:06:47 +08:00
```go

buf := make([]byte, 1500)

for {
n, src, err := packet.ReadFrom(buf)

... buff[:n]
}

```
dawniii
2020-02-28 10:05:59 +08:00
@reus 刚试了下并不会这样,buf 给多大,就只读多大的,有多余的下次能读到。
dawniii
2020-02-28 10:19:10 +08:00
@reus 我试的是 tcp 的情况,楼主说的 udp 应该是要给一个足够的 buf,一次性读完所有内容。
ydongd
2020-02-28 10:35:29 +08:00
最大传输单元( MTU )大概是 1500,具体记不清了。所以在底层读的这里用这么大的 buffer 就够了。如果一个数据大于 1500,在传输层也会分包,所以在接收的地方还需要将数据重组。根据 n, src, err := packet.ReadFrom(buf) 的 src 判断来源。即 @p2p 的方式。
reus
2020-02-28 10:59:25 +08:00
@dawniii 那你试的和这里讨论的,根本就不一样啊。现在说的是读 UDP 时,缓冲区不够大的情况。请重新试验。
mengzhuo
2020-02-28 11:01:55 +08:00
@ydongd 这个 src 不可信的,很多 NAT 只要回过一次包就会 DROP rule。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/648023

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX