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

好记性不如烂笔头,既然不够聪明,就乖乖的做笔记,温故而知新。

本文档用于本人对知识点的梳理和记录

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

 

一、目录

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

二、硬件工具

三、添加TCP多客户端过程

四、总结


 

二、硬件工具

开发板:AT-START-F437

路由器:MERCURY一台

辅助材料:网线若干

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

三、添加TCP多客户端过程

3.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 );

3.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);
	}
}

3.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); 
	}
}

3.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;非常重要!

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑色HS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值