码迷,mamicode.com
首页 > 其他好文 > 详细

关于原子哥ENC28J60网络通信模块接收数据代码的一点失误

时间:2016-08-16 23:59:25      阅读:906      评论:0      收藏:0      [点我收藏+]

标签:

这几天做STM32的ENC28J60网络通信模块,自己在原子哥的代码上进行修改测试,,发现一个问题,电脑和板子进行通信的时候总隔一段时间板子就死机了.

直接源码

struct netbuf *recvbuf;//接收buf
struct pbuf *q;    

err_t recv_err;//接收数据返回信息

u32 data_len = 0; //客户端接收数组的长度

u8 tcp_server_recvbuf[TCP_SERVER_RX_BUFSIZE]; //TCP客户端接收数据缓冲区
memset(tcp_server_recvbuf,0,TCP_SERVER_RX_BUFSIZE);  //数据接收缓冲区清零

if((recv_err = netconn_recv(newconn,&recvbuf)) == ERR_OK) //接收到数据
{

for(q=recvbuf->p;q!=NULL;q=q->next)  //遍历完整个pbuf链表
            {
                //判断要拷贝到TCP_SERVER_RX_BUFSIZE中的数据是否大于TCP_SERVER_RX_BUFSIZE的剩余空间,如果大于
                //的话就只拷贝TCP_SERVER_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
                if(q->len > (TCP_SERVER_RX_BUFSIZE-data_len)) 
                    memcpy(tcp_server_recvbuf+data_len,q->payload,(TCP_SERVER_RX_BUFSIZE-data_len));//拷贝数据
                else 
                    memcpy(tcp_server_recvbuf+data_len,q->payload,q->len);
                
                data_len = data_len + q->len;  
                
                if(data_len > TCP_SERVER_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出    
            }

 

自己修改后的,,其实还没优化好,,先这样吧!不影响下面的叙述

struct netbuf *recvbuf;//接收buf
struct pbuf *q;    

err_t recv_err;//接收数据返回信息

u32 data_len = 0; //客户端接收数组的长度

u8 tcp_server_recvbuf[TCP_SERVER_RX_BUFSIZE]; //TCP客户端接收数据缓冲区
memset(tcp_server_recvbuf,0,TCP_SERVER_RX_BUFSIZE);  //数据接收缓冲区清零

if((recv_err = netconn_recv(newconn,&recvbuf)) == ERR_OK) //接收到数据
{

for(q=recvbuf->p;q!=NULL;q=q->next)  //遍历完整个pbuf链表
            {
                if(q->tot_len > TCP_SERVER_RX_BUFSIZE)//接收的数据大于了接收数组
                {
                    printf("接收的数据大于了接收数组");
                }
                else
                {
                    memcpy(tcp_server_recvbuf+data_len,q->payload,q->len);
                    data_len = data_len + q->len; 
                }
            }

首先介绍一下存数据的这个链表----如果不会链表,,,,那就百度一下吧!或者接着看看也行,,,,,改天我写个关于链表的博客,,,,,

struct pbuf {
  /** next pbuf in singly linked pbuf chain */
  struct pbuf *next;指向下一个链表

  /** pointer to the actual data in the buffer */
  void *payload;指向下一个链表的数据区

  /**
   * total length of this buffer and all next buffers in chain
   * belonging to the same packet.
   *
   * For non-queue packet chains this is the invariant:
   * p->tot_len == p->len + (p->next? p->next->tot_len: 0)
   */
  u16_t tot_len;当前pbuf的数据长度与后面所有的pbuf数据之和

  /** length of this buffer */
  u16_t len;//当前pbuf数据长度
  下面的就不说了,,和我们说的无关,,,,
  /** pbuf_type as u8_t instead of enum to save space */
  u8_t /*pbuf_type*/ type;

  /** misc flags */
  u8_t flags;

  /**
   * the reference count always equals the number of pointers
   * that refer to this pbuf. This can be pointers from an application,
   * the stack itself, or pbuf->next pointers from a chain.
   */
  u16_t ref;
};

技术分享

假设数据来了,因为数据的个数不一定,而每一个链表存数据的个数都是有限的,所以呢就出现了上图,把数据分割依次存入几个链表中

我们要把数据存入

TCP_SERVER_RX_BUFSIZE  自己定义的1000
u8 tcp_server_recvbuf[TCP_SERVER_RX_BUFSIZE]; //TCP客户端接收数据缓冲区
这个数组

是不是应该

技术分享

先看一眼这个,

struct netbuf {
  struct pbuf *p, *ptr;

 

struct netbuf *recvbuf;//接收buf
struct pbuf *q;//定义了一个q 也是用它指向下一个链表同next功能一样   

err_t recv_err;//接收数据返回信息

u32 data_len = 0; //客户端接收数组的长度

u8 tcp_server_recvbuf[TCP_SERVER_RX_BUFSIZE]; //TCP客户端接收数据缓冲区
memset(tcp_server_recvbuf,0,TCP_SERVER_RX_BUFSIZE);  //数据接收缓冲区清零

if((recv_err = netconn_recv(newconn,&recvbuf)) == ERR_OK) //接收到数据,,现在recvbuf->p就是第一个链表的地址了
{

for(q=recvbuf->p;q!=NULL;q=q->next)  //遍历完整个pbuf链表       for(把第一个链表的地址给q, q是空的吗, 指向下一个链表)
            {
其实只需要判断第一个q->tot_len,它记录的是本链表的数据长度(len记录本链表的数据长度)加后面所有的数据长度,,也就是总数据长度
if(q->tot_len > TCP_SERVER_RX_BUFSIZE)//接收的数据大于了接收数组 { printf("接收的数据大于了接收数组"); } else { memcpy(tcp_server_recvbuf+data_len,q->payload,q->len);memcpy(数组的首地址+每一个链表的数据长度累加和, 有效的数据首地址, 对应链表的数据长度) data_len = data_len + q->len; //每一的链表的数据累加和,, } }

 

看一下原子哥的


 //判断要拷贝到TCP_SERVER_RX_BUFSIZE中的数据是否大于TCP_SERVER_RX_BUFSIZE的剩余空间,如果大于
 //的话就只拷贝TCP_SERVER_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
上面说的对,,程序好像,,,,
if
(q->len > (TCP_SERVER_RX_BUFSIZE-data_len)) //一开始data_len=0;第一个链表的长度大于1000吗,接着.....
memcpy(tcp_server_recvbuf
+data_len,q->payload,(TCP_SERVER_RX_BUFSIZE-data_len));//拷贝数据 else memcpy(tcp_server_recvbuf+data_len,q->payload,q->len); data_len = data_len + q->len; if(data_len > TCP_SERVER_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出

我没有过多分析原子哥的接收数据程序一直执行为什么会死机,自己感觉可能会内存泄漏,,找到问题的原因了,挺开心的,,应该说终于找到问题的原因吧!

 

关于原子哥ENC28J60网络通信模块接收数据代码的一点失误

标签:

原文地址:http://www.cnblogs.com/yangfengwu/p/5778224.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!