从长度未知的UDP套接字读取数据

时间:2014-07-11 18:59:09

标签: sockets networking go udp

我怎么能socket.ReadFromUDP事先不知道长度?现在我有这样的事情。

buff := make([]byte, <unknownLength>)
for {
    socket.ReadFromUDP(buff)
    fmt.Println("Bytes read:", buff.Len())
}

我尝试了这个,但它总是读取1024个字节。

buff := make([]byte, 1024)
for {
    bytesRead, _, _ := socket.ReadFromUDP(buff)
    fmt.Println("Bytes read:", bytesRead)
}

我从服务器接收的数据包从几个字节到几个字节不等。

2 个答案:

答案 0 :(得分:10)

UDP套接字接收离散数据报中的消息(因此名称为SOCK_DGRAM)。虽然Go有一个相对干净的网络API,但如果不了解底层套接字(How large should my recv buffer be when calling recv in the socket library),你仍然无法逃脱。

UDP套接字将Read达到接收缓冲区的大小,并将丢弃其余的,因此您无法像在TCP流上那样继续读取。 UDP套接字上的单个接收消耗来自网络的单个数据报。

虽然UDP数据包的理论最大有效负载是65,507,但实际上由于路径MTU限制,您可能不会获得超过1400字节的消息。如果你将缓冲区设置得比这大得多,就像4096字节一样,你会非常安全,但你可以使用64k缓冲区来确定。

虽然在Go中尝试确定待处理的数据包大小是不可行的,但您可以判断是否丢失了数据的价值:

oob := make([]byte, 1024)
n, on, flags, addr, err := c.ReadMsgUDP(buff, oob)
if flags & syscall.MSG_TRUNC != 0 {
    fmt.Println("truncated read")
}

答案 1 :(得分:4)

基本技术是使用比最大预期数据报大的缓冲区。然后,如果你得到一个大小的数据报,你知道它不适合你的应用程序协议并且应该被丢弃,可能是在记录之后,如果发送方出现编程错误,或者你的应用程序协议未完全指定。