OpenEdv-开源电子网

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

咨询个网络实验8 NETCONN_TCP 客户端实验里面关于uCOS的问题

[复制链接]

1

主题

7

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2020-4-28
在线时间
6 小时
发表于 2020-7-31 11:23:33 | 显示全部楼层 |阅读模式
1金钱
大家好,咨询个网络实验8 NETCONN_TCP 客户端实验里面关于uCOS的一个小问题,我在查看tcp_client_demo.c文件时候,看到 tcp客户端任务函数 时候有个疑问,static void tcp_client_thread(void *arg)这个任务是怎么进行切换的,这个任务优先级是这个例程里面优先级最高的而且任务函数里面又没看见有导致它挂起或切换的操作,求各位大神指点迷津


//tcp¿Í»§¶ËÈÎÎñº¯Êý
void tcp_client_thread(void *arg)
{
    u32 data_len = 0;
    struct pbuf *q;
    err_t err,recv_err;
    static ip_addr_t server_ipaddr,loca_ipaddr;
    static u16_t          server_port,loca_port;

    LWIP_UNUSED_ARG(arg);
    server_port = REMOTE_PORT;
    IP4_ADDR(&server_ipaddr, lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]);
   
    while (1)
    {
        tcp_clientconn=netconn_new(NETCONN_TCP);  //´´½¨Ò»¸öTCPÁ´½Ó
        err = netconn_connect(tcp_clientconn,&server_ipaddr,server_port);//Á¬½Ó·þÎñÆ÷
        if(err != ERR_OK)
        {
            netconn_delete(tcp_clientconn); //·µ»ØÖµ²»µÈÓÚERR_OK,ɾ³ýtcp_clientconnÁ¬½Ó
        }
        else if (err == ERR_OK)    //´¦ÀíÐÂÁ¬½ÓµÄÊý¾Ý
        {
            struct netbuf *recvbuf;
            tcp_clientconn->recv_timeout = 10;
            netconn_getaddr(tcp_clientconn,&loca_ipaddr,&loca_port,1); //»ñÈ¡±¾µØIPÖ÷»úIPµØÖ·ºÍ¶Ë¿ÚºÅ
            printf("Á¬½ÓÉÏ·þÎñÆ÷%d.%d.%d.%d,±¾»ú¶Ë¿ÚºÅΪ:%d\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3],loca_port);
            while(1)
            {
                if((tcp_client_flag & LWIP_SEND_DATA) == LWIP_SEND_DATA) //ÓÐÊý¾ÝÒª·¢ËÍ
                {
                    err = netconn_write(tcp_clientconn ,NETBUS_txBuffer,NETBUS_txLength,NETCONN_COPY); //·¢ËÍÊý¾Ý
                    if(err != ERR_OK)
                    {
                        printf("·¢ËÍʧ°Ü\r\n");
                    }
                    tcp_client_flag &= ~LWIP_SEND_DATA;
                }
                    
                if((recv_err = netconn_recv(tcp_clientconn,&recvbuf)) == ERR_OK)  //½ÓÊÕµ½Êý¾Ý
                {   
                    taskENTER_CRITICAL();
                    memset(tcp_client_recvbuf,0,TCP_CLIENT_RX_BUFSIZE);  //Êý¾Ý½ÓÊÕ»º³åÇøÇåÁã
                    for(q=recvbuf->p;q!=NULL;q=q->next)  //±éÀúÍêÕû¸öpbufÁ´±í
                    {
                        //ÅжÏÒª¿½±´µ½TCP_CLIENT_RX_BUFSIZEÖеÄÊý¾ÝÊÇ·ñ´óÓÚTCP_CLIENT_RX_BUFSIZEµÄÊ£Óà¿Õ¼ä£¬Èç¹û´óÓÚ
                        //µÄ»°¾ÍÖ»¿½±´TCP_CLIENT_RX_BUFSIZEÖÐÊ£Ó೤¶ÈµÄÊý¾Ý£¬·ñÔòµÄ»°¾Í¿½±´ËùÓеÄÊý¾Ý
                        if(q->len > (TCP_CLIENT_RX_BUFSIZE-data_len)) memcpy(tcp_client_recvbuf+data_len,q->payload,(TCP_CLIENT_RX_BUFSIZE-data_len));//¿½±´Êý¾Ý
                        else memcpy(tcp_client_recvbuf+data_len,q->payload,q->len);
                        data_len += q->len;      
                        if(data_len > TCP_CLIENT_RX_BUFSIZE) break; //³¬³öTCP¿Í»§¶Ë½ÓÊÕÊý×é,Ìø³ö   
                    }
                    taskEXIT_CRITICAL();
                    data_len=0;  //¸´ÖÆÍê³Éºódata_lenÒªÇåÁã¡£                    
                    printf("%s\r\n",tcp_client_recvbuf);
                    //NETBUS_Respond(tcp_client_recvbuf);
                    netbuf_delete(recvbuf);
                }else if(recv_err == ERR_CLSD)  //¹Ø±ÕÁ¬½Ó
                {
                    netconn_close(tcp_clientconn);
                    netconn_delete(tcp_clientconn);
                    printf("·þÎñÆ÷%d.%d.%d.%d¶Ï¿ªÁ¬½Ó\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]);
                    break;
                }
            }
        }
    }
}


最佳答案

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

就是netconn_connect(),netconn_recv()函数,请求信号量或者消息,请求不到就会产生任务切换。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

15

主题

109

帖子

0

精华

高级会员

Rank: 4

积分
826
金钱
826
注册时间
2016-6-28
在线时间
160 小时
发表于 2020-7-31 11:23:34 | 显示全部楼层
就是netconn_connect(),netconn_recv()函数,请求信号量或者消息,请求不到就会产生任务切换。
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2020-4-28
在线时间
6 小时
 楼主| 发表于 2020-7-31 11:24:38 | 显示全部楼层
源码重新贴出:
源码如下:

//tcp客户端任务函数
static void tcp_client_thread(void *arg)
{
        OS_CPU_SR cpu_sr;
        u32 data_len = 0;
        struct pbuf *q;
        err_t err,recv_err;
        static ip_addr_t server_ipaddr,loca_ipaddr;
        static u16_t                  server_port,loca_port;

        LWIP_UNUSED_ARG(arg);
        server_port = REMOTE_PORT;
        IP4_ADDR(&server_ipaddr, lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]);
      
        while (1)
        {
                tcp_clientconn = netconn_new(NETCONN_TCP);  //创建一个TCP链接
                err = netconn_connect(tcp_clientconn,&server_ipaddr,server_port);//连接服务器
                if(err != ERR_OK)  netconn_delete(tcp_clientconn); //返回值不等于ERR_OK,删除tcp_clientconn连接
                else if (err == ERR_OK)    //处理新连接的数据
                {
                        struct netbuf *recvbuf;
                        tcp_clientconn->recv_timeout = 10;
                        netconn_getaddr(tcp_clientconn,&loca_ipaddr,&loca_port,1); //获取本地IP主机IP地址和端口号
                        printf("连接上服务器%d.%d.%d.%d,本机端口号为:%d\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3],loca_port);
                        while(1)
                        {
                                if((tcp_client_flag & LWIP_SEND_DATA) == LWIP_SEND_DATA) //有数据要发送
                                {
                                        // strlen计数器的工作,它从内存的某个位置开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值(长度不包含'\0')
                    err = netconn_write(tcp_clientconn ,tcp_client_sendbuf,strlen((char*)tcp_client_sendbuf),NETCONN_COPY); //发送tcp_server_sentbuf中的数据
                                        if(err != ERR_OK)
                                        {
                                                printf("发送失败\r\n");
                                        }
                                        tcp_client_flag &= ~LWIP_SEND_DATA;
                                }
                                       
                                if((recv_err = netconn_recv(tcp_clientconn,&recvbuf)) == ERR_OK)  //接收到数据
                                {      
                                        OS_ENTER_CRITICAL(); //关中断
                                        memset(tcp_client_recvbuf,0,TCP_CLIENT_RX_BUFSIZE);  //数据接收缓冲区清零
                                        for(q=recvbuf->p;q!=NULL;q=q->next)  //遍历完整个pbuf链表
                                        {
                                                //判断要拷贝到TCP_CLIENT_RX_BUFSIZE中的数据是否大于TCP_CLIENT_RX_BUFSIZE的剩余空间,如果大于
                                                //的话就只拷贝TCP_CLIENT_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
                                                if(q->len > (TCP_CLIENT_RX_BUFSIZE-data_len)) memcpy(tcp_client_recvbuf+data_len,q->payload,(TCP_CLIENT_RX_BUFSIZE-data_len));//拷贝数据
                                                else memcpy(tcp_client_recvbuf+data_len,q->payload,q->len);
                                                data_len += q->len;         
                                                if(data_len > TCP_CLIENT_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出      
                                        }
                                        OS_EXIT_CRITICAL();  //开中断
                                        data_len=0;  //复制完成后data_len要清零。                                       
                                        printf("%s\r\n",tcp_client_recvbuf);
                                        netbuf_delete(recvbuf);
                                }else if(recv_err == ERR_CLSD)  //关闭连接
                                {
                                        netconn_close(tcp_clientconn);
                                        netconn_delete(tcp_clientconn);
                                        printf("服务器%d.%d.%d.%d断开连接\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]);
                                        break;
                                }
                        }
                }
        }
}

//创建TCP客户端线程
//返回值:0 TCP客户端创建成功
//                其他 TCP客户端创建失败
INT8U tcp_client_init(void)
{
        INT8U res;
        OS_CPU_SR cpu_sr;
      
        OS_ENTER_CRITICAL();        //关中断
        res = OSTaskCreate(tcp_client_thread,(void*)0,(OS_STK*)&TCPCLIENT_TASK_STK[TCPCLIENT_STK_SIZE-1],TCPCLIENT_PRIO); //创建TCP客户端线程
        OS_EXIT_CRITICAL();                //开中断
      
        return res;
}
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165377
金钱
165377
注册时间
2010-12-1
在线时间
2111 小时
发表于 2020-8-2 23:33:50 | 显示全部楼层
帮顶
回复

使用道具 举报

15

主题

109

帖子

0

精华

高级会员

Rank: 4

积分
826
金钱
826
注册时间
2016-6-28
在线时间
160 小时
发表于 2020-9-11 17:36:23 | 显示全部楼层
视频里有说 netconn_recv(tcp_clientconn,&recvbuf)是阻塞型函数, tcp_clientconn->recv_timeout = 10;搞了超时处理。不知道跟这个有没有关系。
回复

使用道具 举报

15

主题

109

帖子

0

精华

高级会员

Rank: 4

积分
826
金钱
826
注册时间
2016-6-28
在线时间
160 小时
发表于 2020-9-11 17:37:31 | 显示全部楼层
这个需要左神回复一下啊,那些闪灯,按键的任务怎么抢占这个任务的??我现在调试总是出现这个任务进去不,不知道什么原因
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2020-4-28
在线时间
6 小时
 楼主| 发表于 2021-2-20 15:21:42 | 显示全部楼层
谢谢大神指点
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-28 17:25

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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