打印
[其它]

AT32F437 UCOSIII系统Lwip下NETCONN编程接口TCP多客户端连接

[复制链接]
354|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
aoyi|  楼主 | 2023-7-19 10:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


一、硬件工具
开发板:AT-START-F437

路由器:MERCURY一台

辅助材料:网线若干

软件工具:KEIL,VS Vode,网络调试助手PC版和Android版

二、添加TCP多客户端过程
2.1 创建连接管理任务、数据处理任务

sys_thread_new("tcp_handle", svr_task, NULL, ECHO_STK_SIZE, ECHO_THREAD_PRIO );
sys_thread_new("tcp_server_thread", tcp_server_thread, NULL, ECHO_STK_SIZE, ECHO_THREAD_PRIO );
2.2 svr_task任务,用于轮询建立TCP连接,conn->acceptmbox.Type = OS_OBJ_TYPE_Q;非常重要,如果不添加,可能会导致netconn_accept和netconn_delete函数进入while等待邮箱数据。client_init函数用于管理和分配多路TCP连接。

void svr_task(void *arg)
{
        OS_ERR         oserr;                                       //错误标志(UCOSIII)

        conn = netconn_new(NETCONN_TCP);                            //创建一个TCP服务器连接
        netconn_bind(conn,IP_ADDR_ANY,TCP_PORT);                 //绑定端口号       
        netconn_listen(conn);                                                   //进入监听模式       

        printf("accepted new connection %p\n", newconn);
   /* Process the new connection. */
   newconn = NULL;
        while(1)
        {
                if(newconn->state != NETCONN_NONE)
                {
                        conn->acceptmbox.Type = OS_OBJ_TYPE_Q;                        //非常重要,必须添加
                        if(netconn_accept(conn, &newconn) == ERR_OK)         //接收到正确的连接请求
                        {
                                newconn->recv_timeout = 200;                //禁止阻塞线程 等待200ms       
                                if(client_init((void *)newconn) != ERR_OK)        //判断 TCP 客户端任务是否创建成功
                                {                                                 //若创建失败
                                        netconn_close(newconn);                 //关闭 TCP client 连接
                                        netconn_delete(newconn);                //删除 TCP client 连接
                                }
                                newconn = NULL;                                                                //连接后复位newconn
                        }
                        newconn->acceptmbox.Type = OS_OBJ_TYPE_Q;                //非常重要,必须添加
                }
                OSTimeDly(300, OS_OPT_TIME_DLY, &oserr);
        }
}

2.3 数据处理任务中轮询接收有数据到来的TCP链路并将数据回传到对应的TCP Client。如果检测TCP 断开,将删除对应的设备信息,确保下一次连接无误。

static void tcp_server_thread(void *arg)
{
        OS_ERR       oserr;
        err_t recv_err;
        void* tx_buf;
        u16_t tx_len=0;
        uint8_t client = 0;
        struct netbuf *recvbuf;               

        while(1)
        {
                if(client < CLIENTMAX){
                if(clientad.num_max != 0){
                       
                for(client=0;client < clientad.num_max;client++){
                        if(clientad.state[client]==1)
                        {
                                if((recv_err = netconn_recv(clientad.conn[client],&recvbuf)) == ERR_OK)          //接收到数据
                                {
                                        tx_buf = recvbuf->p->payload;
                                        tx_len = recvbuf->p->len;
                                        netconn_write(clientad.conn[client], tx_buf, tx_len, NETCONN_COPY);         //接收到的数据发送回去
                               
                                        netbuf_delete(recvbuf);
                                        printf("rev %d data success!\n",client);
                                }
                                else if(recv_err == ERR_CLSD||recv_err==ERR_RST)                                                //关闭连接或复位数据
                                {
                                        client_count--;               
                                        netconn_close(clientad.conn[client]);
                                        clientad.conn[client]->acceptmbox.Type = OS_OBJ_TYPE_Q;                        //非常重要,必须添加
                                        netconn_delete(clientad.conn[client]);                                                        //删除连接
                                        clientad.state[client]=0;                                                                                //第 client->num_max 个设备状态置0 表示客户端已断开
                                        clientad.num_max--;
                                        printf("link close!\n");
                                }
                        }
                }
                if(client >=  clientad.num_max)
                        client=0;
                }
                }
                OSTimeDly(10, OS_OPT_TIME_DLY, &oserr);
        }
}

2.4 相关定义

#define CLIENTMAX                                   10 //最大客户端连接数量

//客户端地址结构体
typedef struct client_ad_t
{
        struct netconn                         *conn[CLIENTMAX];
        uint8_t                                        num[CLIENTMAX];                //客户端连接地址保存(最多20个客户端连接  地址全存这里了)
        uint8_t                                 num_max;                        //客户端已连接设备的数量
        uint8_t                                        state[CLIENTMAX];        //客户端连接状态
}client_ad;

client_ad                 clientad; //TCP客户端地址结构体(全局变量)
四、总结
conn->acceptmbox.Type = OS_OBJ_TYPE_Q;非常重要!
————————————————
版权声明:本文为CSDN博主「黑色HS」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_38933763/article/details/125366128

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

99

主题

3301

帖子

3

粉丝