本帖最后由 FreeRTOS 于 2017-7-8 11:41 编辑
这几天忙里偷闲又研究了LWIP的包缓冲区pbuf,发现一个一直使用的数据接收的错误,具体是在接收回调函数里简单粗暴的直接使用拷贝语句来复制数据包内容: 因为公司的机子一直没有碰到数据包比较大的情况,所以一直没发现上面的接收代码有问题, 直到昨天才想起pbuf是采用链表式内存来保存网络数据的,当数据包长度大于一定值时,问题就出现了。 以发送0x00~0x4F的80字节为例:
LWIP在UDP回调函数里的pbuf链表指针p的tot_len为80,但len字段只有78,意味着80字节的数据不能被一个pbuf保存完
这时如果直接采用memcpy来拷贝的话,最后的2字节无疑是错误的!下面给出了数据读取后数组最后2字节的错误内容:
再深入分析下这个问题,由于LWIP的数据接收采用的是pbuf链表,当数据包比较大时,可以认为LWIP将数据包分块然后连成一个链表, 最后LWIP把这个链表的链表头传递到回调函数,这时用户如果想获取这个链表的内容,就必须读取链表的每个payload才能确保数据正确! 下面贴上本渣自己写的代码:
当调用上面的函数接收后,接收数据正确了:
上面的实验只是试验了数据包没有超出缓冲区的情况,下面以512字节来试验缓冲区大小为256的情况:
进入到Get_PBUF_Payload()函数后可以看到当前的pbuf链表总长度为512:
由于传递进来的maxLen = 256,因此函数返回的成功读取的数据也是256而非512!
后来翻了下原子F7的例程,思路跟本渣的大致一样,不过原子兄的这个代码无法获取实际读取的数据长度:
更多LWIP的pbuf知识请读者自行查阅《Design and Implementation of the lwIPTCP_IP Stack》,当然本渣是不会告诉你这本资料有中文翻译版本的。 最后推荐下五木大神关于LWIP的见解《LwIP协议栈源码详解》,资料问度娘。
|