我怎么能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)
}
我从服务器接收的数据包从几个字节到几个字节不等。
答案 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)
基本技术是使用比最大预期数据报大的缓冲区。然后,如果你得到一个大小的数据报,你知道它不适合你的应用程序协议并且应该被丢弃,可能是在记录之后,如果发送方出现编程错误,或者你的应用程序协议未完全指定。