LWIP udp 回调函数

LWIP udp 收发大包应用

最近因公司一项目需要,udp需一次性接收4K左右的数据,一开始发现Udp_Recv只能接收256BYTE的数据,于是想到了lwipopt.h中缓存池大小的设置,便顺手将缓冲区大小设置到了1500。

//*****************************************************************************
//
// ---------- Pbuf options ----------
//
//*****************************************************************************
#define PBUF_LINK_HLEN                  16          // default is 14
#define PBUF_POOL_BUFSIZE               1500        // 定义单个缓冲区大小
#define ETH_PAD_SIZE                    0           // default is 0

由此便一步步进入误区。(只考虑了单个缓冲区,忘记pbuf链表的后半部分)

后再收发大包数据时发现数据只能在1500BYTE范围内,便方向又跑到了MTU(允许最大传输单元,1500BYTE)的限制中去,一番折腾失败而归,后来发现是自己的Udp_Recv回调函数出了问题,如下:

/*---------------------------------------------------------------------------+
|  Function :                                                                |
|  Task     :                                                                |
+----------------------------------------------------------------------------+
|  Call     :                                                                |
|                                                                            |
|  Parameter:                           -                                    |
|                                                                            |
|  Return   :                           -                                    |
+---------------------------------------------------------------------------*/
static void Udp_Recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
{
    if (p != NULL)
    {
        pcb->remote_ip = *addr;
        pcb->remote_port = port;

        Handle_Recv_DATA(p->payload, p->len);

        pbuf_free(p);
    }
}

错误之处在于误以为(p->payload, p->len)将所有数据带入应用层,后发现只copy了pbuf链表中第一块的数据,也就是前面提到的
#define PBUF_POOL_BUFSIZE 1500 // 定义单个缓冲区大小,这个1500BYTE正好误导我进入了MTU的轨道。

正解:

//*****************************************************************************
//
// ---------- Internal Memory Pool Sizes ----------
//
//*****************************************************************************
#define MEMP_NUM_PBUF                     48    // Default 16
//#define MEMP_NUM_RAW_PCB                4
//#define MEMP_NUM_UDP_PCB                4
#define MEMP_NUM_TCP_PCB                  16    // Default 5
//#define MEMP_NUM_TCP_PCB_LISTEN         8
//#define MEMP_NUM_TCP_SEG                16
//#define MEMP_NUM_REASSDATA              5
//#define MEMP_NUM_ARP_QUEUE              30
//#define MEMP_NUM_IGMP_GROUP             8
#define MEMP_NUM_SYS_TIMEOUT              8
//#define MEMP_NUM_NETBUF                 2
//#define MEMP_NUM_NETCONN                4
//#define MEMP_NUM_TCPIP_MSG_API          8
//#define MEMP_NUM_TCPIP_MSG_INPKT        8
#define PBUF_POOL_SIZE                    16    // Default 16  //缓冲池的个数
//*****************************************************************************
//
// ---------- Pbuf options ----------
//
//*****************************************************************************
#define PBUF_LINK_HLEN                  16          // default is 14
#define PBUF_POOL_BUFSIZE               1500        // 定义单个缓冲区大小
                                                    // default is LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN)
#define ETH_PAD_SIZE                    0           // default is 0

以上的PBUF_POOL_BUFSIZE * PBUF_POOL_SIZE便是缓冲区的总大小,而数据需要从逐个缓存中copy出。
于是回调改为如下:

/*---------------------------------------------------------------------------+
|  Function :                                                                |
|  Task     :                                                                |
+----------------------------------------------------------------------------+
|  Call     :                                                                |
|                                                                            |
|  Parameter:                           -                                    |
|                                                                            |
|  Return   :                           -                                    |
+---------------------------------------------------------------------------*/
static void Udp_Recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
{
	struct pbuf *p_r;
	WORD  u_wRecvLen = 0;

    if (p != NULL)
    {
        pcb->remote_ip = *addr;
        pcb->remote_port = port;

        memset(g_byRecvHMIData, 0, sizeof(g_byRecvHMIData));
        for(p_r = p; p_r != NULL; p_r = p_r->next)
        {
        	memcpy(g_byRecvHMIData+u_wRecvLen, p_r->payload, p_r->len);
        	u_wRecvLen += p_r->len;
        }

        Handle_Recv_DATA(g_byRecvHMIData, u_wRecvLen);

        pbuf_free(p);
    }
}

便可从缓冲区中取出所有数据。

你可能感兴趣的:(物联网)