stm32开发之threadx+netxduo(tcp 客户端使用记录)
前言
- 本篇涉及到的内容: threadx之动态内存的实现记录、stm32开发之实现代码之间解耦(借助链接文件和关键字section)
代码
/* * Copyright (c) 2024-2024,shchl * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2024-4-9 shchl first version */ #include "includes.h" #if 1 #define TCP_CLIENT_STACK_SIZE 4096 /*任务栈大小*/ #define TCP_CLIENT_PRIORITY 4 /*优先级*/ #define PACKET_SIZE 1536 /*数据包大小*/ #define POOL_SIZE ((sizeof(NX_PACKET) + PACKET_SIZE) * 16) /*数据包池大小(16个缓冲区)*/ #define TCP_LOCAL_IP IP_ADDRESS(192, 168, 8, 9) /*本地ip*/ #define TCP_LOCAL_PORT 8000 #define TCP_LOCAL_SUB_MASH IP_ADDRESS(255,255,255,0) /*本地ip*/ #define TCP_SERVER_PORT 8080 #define TCP_SEVER_IP IP_ADDRESS(192, 168, 8, 2) static ULONG error_counter; static NX_IP tcp_client_ip; static TX_THREAD tcp_client_thread; static NX_PACKET_POOL tcp_client_packet_pool; static NX_TCP_SOCKET client_socket; static void tcp_client_entry(ULONG input); static inline void status_check(UINT stat) { if (stat) { error_counter++; // todo } } int app_task_tcp_client_thread_create() { UINT status; /* Create the main thread. */ tx_thread_create(&tcp_client_thread, "tcp client thread", tcp_client_entry, 0, app_malloc(TCP_CLIENT_STACK_SIZE), TCP_CLIENT_STACK_SIZE, TCP_CLIENT_PRIORITY, TCP_CLIENT_PRIORITY, TX_NO_TIME_SLICE, TX_AUTO_START); /* Create a packet pool. */ status = nx_packet_pool_create(&tcp_client_packet_pool, "NetX Main Packet Pool", PACKET_SIZE, app_malloc(POOL_SIZE), POOL_SIZE); status_check(status); /* Create an IP instance. */ status = nx_ip_create(&tcp_client_ip, "ip instance", TCP_LOCAL_IP, TCP_LOCAL_SUB_MASH, &tcp_client_packet_pool, nx_stm32_eth_driver, app_malloc(2048), 2048, 1); status_check(status); /* Enable ARP and supply ARP cache memory for IP Instance 0. */ status = nx_arp_enable(&tcp_client_ip, app_malloc(1024), 1024); /* Check ARP enable status. */ status_check(status); /* Enable ICMP */ status = nxd_icmp_enable(&tcp_client_ip); status_check(status); /* Enable TCP processing for both IP instances. */ status = nx_tcp_enable(&tcp_client_ip); status_check(status); return NX_SUCCESS; } static void tcp_client_release_resource(NX_TCP_SOCKET *socket_ptr); static UINT tcp_client_build_connection(NX_TCP_SOCKET *socket_ptr, NXD_ADDRESS *server_addr); static void tcp_client_entry(ULONG input) { NX_PARAMETER_NOT_USED(input); UINT status; NX_PACKET *my_packet; ULONG length; NXD_ADDRESS server_ipv4_address; ULONG actual_status; /* 确保 IP 实例已初始化。 */ do { /* 等待 1 秒钟,让 内部 IP 线程完成其初始化。. */ status = nx_ip_status_check(&tcp_client_ip, NX_IP_INITIALIZE_DONE, &actual_status, NX_IP_PERIODIC_RATE); } while (status != NX_SUCCESS); /* set the TCP server addresses. */ server_ipv4_address.nxd_ip_version = NX_IP_VERSION_V4; server_ipv4_address.nxd_ip_address.v4 = TCP_SEVER_IP; /* Loop to repeat things over and over again! */ while (1) { /*建立连接*/ do { tx_thread_sleep(1000);/*建立连接失败等待1s*/ status = tcp_client_build_connection(&client_socket, &server_ipv4_address); } while (status); /*和服务端通讯(todo 业务逻辑切入点)*/ { retry_send: status = nx_packet_allocate(&tcp_client_packet_pool, &my_packet, NX_TCP_PACKET, NX_WAIT_FOREVER); #define SEND_DATA "hello server, i is client" /* Check status. */ if (status != NX_SUCCESS) { tx_log("Error nx_packet_allocate: 0x%x\n", status); break; } /* Write ABCs into the packet payload! */ nx_packet_data_append(my_packet, SEND_DATA, sizeof(SEND_DATA), &tcp_client_packet_pool, TX_WAIT_FOREVER); status = nx_packet_length_get(my_packet, &length); if ((status) || (length != sizeof(SEND_DATA))) { error_counter++; } /* Send the packet out! */ status = nx_tcp_socket_send(&client_socket, my_packet, NX_IP_PERIODIC_RATE); /* Determine if the status is valid. */ if (status) { error_counter++; tx_log("send error:%#x\r\n", status); nx_packet_release(my_packet); } else { tx_thread_sleep(200); goto retry_send; } } /*释放相关资源*/ tcp_client_release_resource(&client_socket); } } NET_X_APP_EXPORT(app_task_tcp_client_thread_create); // 建立连接 static UINT tcp_client_build_connection(NX_TCP_SOCKET *socket_ptr, NXD_ADDRESS *server_addr) { UINT status; /* Create a socket. */ status = nx_tcp_socket_create(&tcp_client_ip, socket_ptr, "Client Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, PACKET_SIZE, NX_NULL, NX_NULL); status_check(status); /* Bind the socket. */ status = nx_tcp_client_socket_bind(socket_ptr, TCP_LOCAL_PORT, NX_WAIT_FOREVER); status_check(status); /* Attempt to connect the socket. */ status = nxd_tcp_client_socket_connect(socket_ptr, server_addr, TCP_SERVER_PORT, NX_IP_PERIODIC_RATE); if (status) { // 连接失败,清理资源 tcp_client_release_resource(socket_ptr); } return status; } // 资源释放 static void tcp_client_release_resource(NX_TCP_SOCKET *socket_ptr) { UINT status = 0; /*socket 状态处于已经建立连接或等待关闭,则需要关闭连接*/ if (socket_ptr->nx_tcp_socket_state == NX_TCP_ESTABLISHED || socket_ptr->nx_tcp_socket_state == NX_TCP_CLOSE_WAIT) { status = nx_tcp_socket_disconnect(&client_socket, NX_IP_PERIODIC_RATE); } /* Determine if the status is valid. */ if (status) { tx_log("nx_tcp_socket_disconnect error:%#x\r\n", status); error_counter++; } /* Unbind the socket. */ status = nx_tcp_client_socket_unbind(&client_socket); /* Check for error. */ if (status) { tx_log("nx_tcp_client_socket_unbind error:%#x\r\n", status); error_counter++; } /* Delete the socket. */ status = nx_tcp_socket_delete(&client_socket); /* Check for error. */ if (status) { tx_log("nx_tcp_socket_delete error:%#x\r\n", status); error_counter++; } } #endif
测试结果(ok)
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。