OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9948|回复: 11

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

[复制链接]

5

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
98
金钱
98
注册时间
2016-7-14
在线时间
44 小时
发表于 2016-7-14 15:00:12 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 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\r\n";
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("发送失败\r\n");
                                                netbuf_delete(sentbuf);      //删除buf
                                        }
                                        udp_flag &= ~LWIP_SEND_DATA;        //清除数据发送标志
                                        netbuf_delete(sentbuf);              //删除buf
                                }        
                                OSTimeDlyHMSM(0,0,0,1);  //延时1ms
                        }
                }else printf("UDP绑定失败\r\n");
        }else printf("UDP连接创建失败\r\n");
}

//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连接失败\r\n");
        }else printf("UDP连接创建失败\r\n");
}

//创建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]





串口调试助手显示的数据的大小为137326

串口调试助手显示的数据的大小为137326

网络调试助手显示的数据大小为180032

网络调试助手显示的数据大小为180032

STM32-Template_ETH_UCOSII _NETCONNUDP_两个线程.zip

1.69 MB, 下载次数: 435

程序源代码

最佳答案

查看完整内容[请看2#楼]

用TCP吧,我测试可以到5MB/S
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2016-7-14 15:00:13 | 显示全部楼层
aimjoe 发表于 2016-7-17 08:18
原子哥,也不是很快大约1ms ,传输20个字节,使用UDP丢包很严重

用TCP吧,我测试可以到5MB/S
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2016-7-14 15:14:53 | 显示全部楼层
超过了STM32的处理能力肯定会丢。
开往春天的手扶拖拉机
回复

使用道具 举报

5

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
98
金钱
98
注册时间
2016-7-14
在线时间
44 小时
 楼主| 发表于 2016-7-14 15:17:56 | 显示全部楼层
zuozhongkai 发表于 2016-7-14 15:14
超过了STM32的处理能力肯定会丢。

原子哥说可以实现1ms间隔狂发数据
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2016-7-14 15:23:54 | 显示全部楼层
aimjoe 发表于 2016-7-14 15:17
原子哥说可以实现1ms间隔狂发数据

那得会优化,才能做到。
开往春天的手扶拖拉机
回复

使用道具 举报

5

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
98
金钱
98
注册时间
2016-7-14
在线时间
44 小时
 楼主| 发表于 2016-7-14 15:29:47 | 显示全部楼层
我在这里抛砖引玉,大家提提自己的想法
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2016-7-15 23:28:41 | 显示全部楼层
aimjoe 发表于 2016-7-14 15:29
我在这里抛砖引玉,大家提提自己的想法

你要多块的速度啊?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

5

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
98
金钱
98
注册时间
2016-7-14
在线时间
44 小时
 楼主| 发表于 2016-7-17 08:18:46 | 显示全部楼层
正点原子 发表于 2016-7-15 23:28
你要多块的速度啊?

原子哥,也不是很快大约1ms ,传输20个字节,使用UDP丢包很严重
回复

使用道具 举报

5

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
98
金钱
98
注册时间
2016-7-14
在线时间
44 小时
 楼主| 发表于 2016-7-23 09:26:25 | 显示全部楼层
使用TCP以后效果很好,没有丢包的情况产生,谢谢原子哥
回复

使用道具 举报

21

主题

134

帖子

0

精华

高级会员

Rank: 4

积分
624
金钱
624
注册时间
2014-11-11
在线时间
161 小时
发表于 2016-11-11 22:16:56 | 显示全部楼层
aimjoe 发表于 2016-7-23 09:26
使用TCP以后效果很好,没有丢包的情况产生,谢谢原子哥

您好   我最近也在调这个东西   方便参考一下你的代码吗   谢谢  不胜感激。。。。
回复

使用道具 举报

6

主题

46

帖子

0

精华

初级会员

Rank: 2

积分
138
金钱
138
注册时间
2013-9-28
在线时间
13 小时
发表于 2017-7-28 20:20:03 | 显示全部楼层
aimjoe 发表于 2016-7-17 08:18
原子哥,也不是很快大约1ms ,传输20个字节,使用UDP丢包很严重

每隔1ms发一个包,每个包的数据大小是20个字节?
回复

使用道具 举报

1

主题

10

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2017-10-17
在线时间
3 小时
发表于 2018-2-27 10:45:13 | 显示全部楼层
正点原子 发表于 2016-7-14 15:00
用TCP吧,我测试可以到5MB/S

是用什么软件测的啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-8 16:34

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表