UDP分两次接收数据包 MSG_PEEK
程序员文章站
2024-03-18 09:15:46
...
问题:
今天在测试e_link协议时,使用SOCK_DGRAM UDP连接服务器,由于协议由定长头部,加数据组成,且头部中包含了数据的长度,因此设计时分两次进行接收。
先接收头部,解析出数据长度,再次接收数据。
但头部接收正常,但数据就读不到了...
socket(AF_INET, SOCK_DGRAM, 0)
connet(ser_addr, addr_len)
recv(sock, head, HEADER, 0)
data_len = ntohl(head->length)
recv(sock, head->data, data_len, 0) //这里就读不到数据了。
经过查找,原因为协议栈收到UDP的数据报文重组后就放到sock的队列上(一个skbuff),当读取部分数据后, 这个skbuff就被释放掉了(不同于TCP,它有的是整个数据缓冲队列)。
目前没有setsockopt支持 UDP的数据读取,来达到一个数据包分多次读取的字段。
解决方案:
在读取头部时,采用如下
recve(sock, head, HEADER, MSG_PEEK)
这样仅仅是偷窥(peek)一下数据,得知其数据的长度(不会影响 select 以及下一次读取),然后再一次性读完。
data_len = ntohl(head->length)
recv(sock, head, HEADER + data_len, 0)