欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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)