NETCONN_UDP实验 丢包严重,请问如何提高传输效率并减少丢包率,已经使用两个线程收发数据,附上源代码

2019-07-20 09:28发布

本帖最后由 aimjoe 于 2016-7-14 15:27 编辑

利用原子哥的LWIP教程的第17讲 NETCONN_UDP实验源代码,自己改进了一下,将发送和接收数据分成两个线程来写。在发送间隔为2ms的情况下,丢包依然很严重。请问各位如何提高传输效率并减少丢包率。记得原子哥在这一课中讲过可以使用两个线程和直接操作寄存器的方式来提高性能,我已经实现用两个线程分别用来收发数据,但是直接操作寄存器怎么实现?使用的是STM32F4,大家来讨论一下如何提高性能
已经将宏LWIP_SO_RCVTIMEO 定义为0,以避免阻塞线程。
#define LWIP_SO_RCVTIMEO                0  //通过定义LWIP_SO_RCVTIMEO使能netconn结构体中recv_timeout,使用recv_timeout可以避免阻塞线程

[mw_shl_code=applescript,true]#include "udp_demo.h"
#include "lwip_comm.h"
#include "usart.h"
#include "led.h"
#include "includes.h"
#include "lwip/api.h"
#include "lwip/lwip_sys.h"
#include "string.h"
//UDP发送任务
#define UDP_SEND_PRIO                6
//任务堆栈大小
#define UDP_SEND_STK_SIZE        300
//任务堆栈
OS_STK UDP_SEND_TASK_STK[UDP_SEND_STK_SIZE];
//udp任务函数
static void udp_send_thread(void *arg);

//UDP发送任务
#define UDP_RECV_PRIO                7
//任务堆栈大小
#define UDP_RECV_STK_SIZE        300
//任务堆栈
OS_STK UDP_RECV_TASK_STK[UDP_RECV_STK_SIZE];
//udp任务函数
static void udp_recv_thread(void *arg);


u8 udp_demo_recvbuf[UDP_DEMO_RX_BUFSIZE];        //UDP接收数据缓冲区
//UDP发送数据内容
const char *udp_demo_sendbuf="Explorer STM32F407 NETCONN UDP demo send data ";
u8 udp_flag;                                                        //UDP数据发送标志位

static struct netconn *udpconn;
struct ip_addr destipaddr;
err_t connect_err;

//udp发送任务函数
static void udp_send_thread(void *arg)
{
        err_t err;        
        static struct netbuf  *sentbuf;
        LWIP_UNUSED_ARG(arg);
               
        udpconn = netconn_new(NETCONN_UDP);  //创建一个UDP链接        
        netconn_bind(udpconn,IP_ADDR_ANY,UDP_DEMO_PORT);
        IP4_ADDR(&destipaddr,lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]); //构造目的IP地址
        connect_err = netconn_connect(udpconn,&destipaddr,UDP_DEMO_PORT);         //连接到远端主机

        
        
        if(udpconn != NULL)  //创建UDP连接成功
        {
                if(connect_err == ERR_OK)//连接成功
                {
                        while(1)
                        {
                                if((udp_flag & LWIP_SEND_DATA) == LWIP_SEND_DATA) //有数据要发送
                                {
                                        sentbuf = netbuf_new();
                                        netbuf_alloc(sentbuf,strlen((char *)udp_demo_sendbuf));
                                        memcpy(sentbuf->p->payload,(void*)udp_demo_sendbuf,strlen((char*)udp_demo_sendbuf));
                                        err = netconn_send(udpconn,sentbuf);          //将netbuf中的数据发送出去
                                        if(err != ERR_OK)
                                        {
                                                printf("发送失败 ");
                                                netbuf_delete(sentbuf);      //删除buf
                                        }
                                        udp_flag &= ~LWIP_SEND_DATA;        //清除数据发送标志
                                        netbuf_delete(sentbuf);              //删除buf
                                }        
                                OSTimeDlyHMSM(0,0,0,1);  //延时1ms
                        }
                }else printf("UDP绑定失败 ");
        }else printf("UDP连接创建失败 ");
}

//udp接收任务函数
static void udp_recv_thread(void *arg)
{
        OS_CPU_SR cpu_sr;
        
        struct pbuf *q;
  u32 data_len = 0;
        static struct netbuf  *recvbuf;
        LWIP_UNUSED_ARG(arg);

        if(udpconn != NULL)  //创建UDP连接成功
        {
                if(connect_err == ERR_OK)//连接成功
                {
                        while(1)
                        {
                                netconn_recv(udpconn,&recvbuf); //接收数据
                                if(recvbuf != NULL)          //接收到数据
                                {
                                        OS_ENTER_CRITICAL(); //关中断
                                        memset(udp_demo_recvbuf,0,UDP_DEMO_RX_BUFSIZE);  //数据接收缓冲区清零
                                        for(q=recvbuf->p;q!=NULL;q=q->next)  //遍历完整个pbuf链表
                                        {
                                                //判断要拷贝到UDP_DEMO_RX_BUFSIZE中的数据是否大于UDP_DEMO_RX_BUFSIZE的剩余空间,如果大于
                                                //的话就只拷贝UDP_DEMO_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
                                                if(q->len > (UDP_DEMO_RX_BUFSIZE-data_len)) memcpy(udp_demo_recvbuf+data_len,q->payload,(UDP_DEMO_RX_BUFSIZE-data_len));//拷贝数据
                                                else memcpy(udp_demo_recvbuf+data_len,q->payload,q->len);
                                                data_len += q->len;         
                                                if(data_len > UDP_DEMO_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出        
                                        }
                                        OS_EXIT_CRITICAL();  //开中断
                                        data_len=0;  //复制完成后data_len要清零。
                                        printf("%s",udp_demo_recvbuf);  //打印接收到的数据
                                        netbuf_delete(recvbuf);      //删除buf
                                }else OSTimeDlyHMSM(0,0,0,1);  //延时1ms
                        }
                }else printf("UDP连接失败 ");
        }else printf("UDP连接创建失败 ");
}

//创建UDP线程
//返回值:0 UDP创建成功
//                其他 UDP创建失败
INT8U udp_demo_init(void)
{
        INT8U res;
        OS_CPU_SR cpu_sr;
        
        OS_ENTER_CRITICAL();        //关中断
        res = OSTaskCreate(udp_send_thread,(void*)0,(OS_STK*)&UDP_SEND_TASK_STK[UDP_SEND_STK_SIZE-1],UDP_SEND_PRIO); //创建UDP线程
        res = OSTaskCreate(udp_recv_thread,(void*)0,(OS_STK*)&UDP_RECV_TASK_STK[UDP_RECV_STK_SIZE-1],UDP_RECV_PRIO); //创建UDP线程        
        OS_EXIT_CRITICAL();                //开中断
        
        return res;
}
[/mw_shl_code]





友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。