c
复制代码
/*
* 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