硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2870|回复: 4
收起左侧

[ThreadX全家桶] ThreadX NetXDUO的TCP客户端测试代码详细注释版(2021-12-27)

[复制链接]

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117568
QQ
发表于 2021-12-27 03:20:54 | 显示全部楼层 |阅读模式


完整例子下载和对应教程:
https://forum.anfulai.cn/forum.php?mod=viewthread&tid=104619

  1. /*
  2. *********************************************************************************************************
  3. *
  4. *        模块名称 : 网络协议栈测试
  5. *        文件名称 : demo_dm9162_netx.c
  6. *        版    本 : V1.0
  7. *        说    明 : 测试的功能说明
  8. *              1. 默认IP地址192.168.28.245,在本文件配置,用户可根据需要修改。
  9. *              2. 可以在电脑端用网络调试软件创建TCP Client连接此服务器端,端口号1001。
  10. *              3. 实现了一个简单的回环通信,用户使用上位机发送的数据通过板子返回到上位机。
  11. *
  12. *        修改记录 :
  13. *                版本号   日期         作者        说明
  14. *                V1.0    2021-01-30   Eric2013     首发
  15. *
  16. *        Copyright (C), 2018-2030, 安富莱电子 www.armfly.com
  17. *
  18. *********************************************************************************************************
  19. */       
  20. #include "includes.h"       



  21. /*
  22. *********************************************************************************************************
  23. *                                            IP相关
  24. *********************************************************************************************************
  25. */
  26. /* 远程服务器端口和IP */
  27. #define TCP_SERVER_PORT                 1001
  28. #define TCP_SERVER_ADDRESS              IP_ADDRESS(192, 168, 28, 146)

  29. /* 本地IP地址 */
  30. #define IP_ADDR0                        192
  31. #define IP_ADDR1                        168
  32. #define IP_ADDR2                        28
  33. #define IP_ADDR3                        245

  34. /* 本地端口号 */
  35. #define DEFAULT_PORT                    1000

  36. /*
  37. *********************************************************************************************************
  38. *                                            NetX任务和通信组件
  39. *********************************************************************************************************
  40. */
  41. /* 上电先将其设置到低优先级,待网线插入后提升优先级到3 */
  42. #define  APP_CFG_TASK_NETX_PRIO                           28u   
  43. #define  APP_CFG_TASK_NETX_STK_SIZE                     4096u
  44. static   uint64_t  AppTaskNetXStk[APP_CFG_TASK_NETX_STK_SIZE/8];

  45. /* 提升NetX处理任务优先级到3 */
  46. #define  APP_CFG_TASK_NETX_PRIO1                           3u

  47. /* 提升NetX应用任务优先级到6 */
  48. #define  APP_CFG_TASK_NetXPro_PRIO1                        6u

  49. NX_TCP_SOCKET TCPSocket;
  50. TX_SEMAPHORE  Semaphore;


  51. /*
  52. *********************************************************************************************************
  53. *                                            NetX任务和通信组件
  54. *********************************************************************************************************
  55. */
  56. UCHAR data_buffer[4096];

  57. NX_PACKET_POOL    pool_0;
  58. NX_IP             ip_0;  

  59. /* 数据包内存池 */
  60. #define PACKET_SIZE          1536
  61. #define NX_PACKET_POOL_SIZE  ((PACKET_SIZE + sizeof(NX_PACKET)) * 20)
  62.        
  63. ULONG  packet_pool_area[NX_PACKET_POOL_SIZE/4 + 4];

  64. /* ARP缓存 */
  65. ULONG    arp_space_area[512 / sizeof(ULONG)];                                                      
  66. ULONG    error_counter;

  67. #define PRINT_DATA(addr, port, data)        do {                                            \
  68.                                                   printf("[%lu.%lu.%lu.%lu:%u] -> '%s' \r\n", \
  69.                                                   (addr >> 24) & 0xff,                      \
  70.                                                   (addr >> 16) & 0xff,                      \
  71.                                                   (addr >> 8) & 0xff,                       \
  72.                                                   (addr & 0xff), port, data);               \
  73.                                                } while(0)

  74. extern TX_THREAD   AppTaskNetXProTCB;
  75. extern TX_THREAD   *netx_thread_ptr;                                               
  76. extern VOID  nx_driver_stm32h7xx(NX_IP_DRIVER *driver_req_ptr);
  77.                                              
  78.                                                
  79. /*
  80. *********************************************************************************************************
  81. *        函 数 名: NetXTest
  82. *        功能说明: TCPnet应用
  83. *        形    参: 无
  84. *        返 回 值: 无
  85. *********************************************************************************************************
  86. */   
  87. void NetXTest(void)
  88. {
  89.     UINT status;
  90.     UINT ret;
  91.     ULONG socket_state;
  92.     UINT old_priority;

  93.     NX_PACKET *RecPacket;
  94.     NX_PACKET *TraPacket;

  95.     ULONG bytes_read;
  96.        
  97.         ULONG peer_ip_address;
  98.         ULONG peer_port;
  99.    
  100.     uint8_t sendbuf[20];
  101.     uint32_t count = 0;
  102.    

  103.     /* 初始化NetX */
  104.     nx_system_initialize();

  105.     /* 创建内存池 */
  106.     status =  nx_packet_pool_create(&pool_0,                                       /* 内存池控制块 */
  107.                                      "NetX Main Packet Pool",                      /* 内存池名 */
  108.                                      1536,                                         /* 内存池每个数据包大小,单位字节
  109.                                                                                       此值必须至少为 40 个字节,并且还必须可以被 4 整除 */
  110.                                                                          (ULONG*)(((int)packet_pool_area + 15) & ~15) ,/* 内存池地址,此地址必须ULONG对齐 */
  111.                                      NX_PACKET_POOL_SIZE);                         /* 内存池大小 */                  
  112.          
  113.     /* 检测创建是否失败 */
  114.     if (status) error_counter++;

  115.     /* 例化IP */
  116.     status = nx_ip_create(&ip_0,                                                   /* IP实例控制块 */                                    
  117.                             "NetX IP Instance 0",                                  /* IP实例名 */     
  118.                             IP_ADDRESS(IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3),    /* IP地址 */
  119.                             0xFFFFFF00UL,                                          /* 子网掩码 */
  120.                             &pool_0,                                               /* 内存池 */
  121.                                                         nx_driver_stm32h7xx,                                   /* 网卡驱动 */
  122.                             (UCHAR*)AppTaskNetXStk,                                /* IP任务栈地址 */
  123.                             sizeof(AppTaskNetXStk),                                /* IP任务栈大小,单位字节 */
  124.                             APP_CFG_TASK_NETX_PRIO);                               /* IP任务优先级 */
  125.                            
  126.             
  127.     /* 检测创建是否失败 */
  128.     if (status) error_counter++;

  129.     /* 使能ARP,并提供ARP缓存 */
  130.     status =  nx_arp_enable(&ip_0,                     /* IP实例控制块 */
  131.                                                         (void *)arp_space_area,    /* ARP缓存地址 */
  132.                                                         sizeof(arp_space_area));   /* 每个 ARP 条目均为 52 个字节,因此,ARP 条目总数是52字节整数倍 */

  133.     /* 使能fragment */   
  134.     status = nx_ip_fragment_enable(&ip_0);

  135.     /* 检测使能成功 */
  136.     if (status) error_counter++;

  137.     /* 使能TCP */
  138.     status =  nx_tcp_enable(&ip_0);

  139.     /* 检测使能成功 */
  140.     if (status) error_counter++;

  141.     /* 使能UDP  */
  142.     status =  nx_udp_enable(&ip_0);

  143.     /* 检测使能成功 */
  144.     if (status) error_counter++;

  145.     /* 使能ICMP */
  146.     status =  nx_icmp_enable(&ip_0);

  147.     /* 检测使能成功 */
  148.     if (status) error_counter++;   
  149.    
  150.     /* NETX初始化完毕后,重新设置优先级 */
  151.     tx_thread_priority_change(netx_thread_ptr, APP_CFG_TASK_NETX_PRIO1, &old_priority);
  152.     tx_thread_priority_change(&AppTaskNetXProTCB, APP_CFG_TASK_NetXPro_PRIO1, &old_priority);
  153.    
  154.     ////////////////////////////////////////////////////////////////////////////////////////////////
  155.     /* 创建TCP Socket */
  156.     ret = nx_tcp_socket_create(&ip_0,                 /* IP实例控制块 */   
  157.                                &TCPSocket,            /* TCP控制块 */
  158.                                "TCP Server Socket",   /* TCP Socket名 */
  159.                                NX_IP_NORMAL,          /* IP服务类型 */
  160.                                NX_FRAGMENT_OKAY,      /* 使能IP分段 */
  161.                                NX_IP_TIME_TO_LIVE,    /* 指定一个 8 位的值,用于定义此数据包在被丢弃之前可通过的路由器数目 */
  162.                                4320,                  /* TCP Socket接收队列中允许的最大字节数 */
  163.                                NX_NULL,               /* 用于在接收流中检测到紧急数据时调用的回调函数 */
  164.                                NX_NULL);              /* TCP Socket另一端发出断开连接时调用的回调函数 */
  165.     if (ret)
  166.     {
  167.                 Error_Handler(__FILE__, __LINE__);   
  168.     }
  169.    
  170.     /* 绑定端口 */
  171.     ret =  nx_tcp_client_socket_bind(&TCPSocket, DEFAULT_PORT, NX_WAIT_FOREVER);

  172.     if (ret != NX_SUCCESS)
  173.     {
  174.         Error_Handler(__FILE__, __LINE__);   
  175.     }

  176.     /* 连接远程服务器 */
  177.     ret = nx_tcp_client_socket_connect(&TCPSocket, TCP_SERVER_ADDRESS, TCP_SERVER_PORT, NX_WAIT_FOREVER);

  178.     if (ret != NX_SUCCESS)
  179.     {
  180.         Error_Handler(__FILE__, __LINE__);   
  181.     }

  182.    
  183.         while(1)
  184.         {
  185.         TX_MEMSET(data_buffer, '\0', sizeof(data_buffer));

  186.         /* 获取socket状态 */
  187.         nx_tcp_socket_info_get(&TCPSocket,     /* TCP Socket控制块 */
  188.                                        NULL,           /* 发送的TCP数据包总数目 */
  189.                                        NULL,           /* 发送的TCP总字节数 */
  190.                                        NULL,           /* 接收TCP数据包总数目 */
  191.                                        NULL,           /* 接收的TCP总字节数 */
  192.                                        NULL,           /* 重新传输的TCP数据包总数目 */
  193.                                        NULL,           /* Socket上TCP排队的TCP数据包总数 */
  194.                                        NULL,           /* Socket上有校验和错误的TCP数据包总数 */
  195.                                        &socket_state,  /* Socket当前状态 */
  196.                                        NULL,           /* 仍在排队等待ACK的发送数据包总数 */
  197.                                        NULL,           /* 当前发送窗口大小 */
  198.                                        NULL);          /* 当前接收窗口大小 */

  199.         /* 如果连接还没有建立,继续接受新连接,成功的话开启接收数据 */
  200.         if(socket_state != NX_TCP_ESTABLISHED)
  201.         {
  202.             /* 绑定端口 */
  203.             ret =  nx_tcp_client_socket_bind(&TCPSocket, DEFAULT_PORT, NX_WAIT_FOREVER);

  204.             if (ret != NX_SUCCESS)
  205.             {
  206.                 Error_Handler(__FILE__, __LINE__);   
  207.             }

  208.             /* 连接远程服务器 */
  209.             ret = nx_tcp_client_socket_connect(&TCPSocket, TCP_SERVER_ADDRESS, TCP_SERVER_PORT, NX_WAIT_FOREVER);

  210.             if (ret != NX_SUCCESS)
  211.             {
  212.                 Error_Handler(__FILE__, __LINE__);   
  213.             }
  214.         }
  215.         
  216.         if((socket_state == NX_TCP_ESTABLISHED)&&(ret == NX_SUCCESS))
  217.         {
  218.                
  219.             /* 接收TCP客户端发的TCP数据包 */
  220.             ret = nx_tcp_socket_receive(&TCPSocket,        /* TCP Socket控制块 */
  221.                                                     &RecPacket,      /* 接收到的数据包 */
  222.                                                     NX_WAIT_FOREVER);  /* 永久等待 */

  223.             if (ret == NX_SUCCESS)
  224.             {
  225.                
  226.                                 /* 获取客户端的IP地址和端口 */
  227.                                 nx_tcp_socket_peer_info_get(&TCPSocket,       /* TCP Socket控制块 */
  228.                                                                                         &peer_ip_address, /* 远程IP地址 */
  229.                                                                                         &peer_port);      /* 远程端口号 */

  230.                 /* 获取客户端发来的数据 */
  231.                 nx_packet_data_retrieve(RecPacket,    /* 接收到的数据包 */
  232.                                                         data_buffer,    /* 解析出数据 */
  233.                                                         &bytes_read);   /* 数据大小 */

  234.                 /* 打印接收到数据 */
  235.                 PRINT_DATA(peer_ip_address, (unsigned int)peer_port, data_buffer);

  236.                 nx_packet_release(RecPacket);
  237.                
  238.                 /* 申请发送数据包 */
  239.                 ret = nx_packet_allocate(&pool_0, &TraPacket, NX_TCP_PACKET, TX_WAIT_FOREVER);

  240.                 if (ret)
  241.                 {
  242.                     Error_Handler(__FILE__, __LINE__);  
  243.                 }

  244.                 sprintf((char *)sendbuf, "sendbuf = %d\r\n", count++);
  245.                
  246.                 /*将要发送的数据附加到TraPacket */
  247.                 ret = nx_packet_data_append(TraPacket, (VOID *)sendbuf, strlen((char *)sendbuf), &pool_0, TX_WAIT_FOREVER);

  248.                 if (ret)
  249.                 {
  250.                     Error_Handler(__FILE__, __LINE__);
  251.                 }
  252.    
  253.                 /* 发送数据,注意发送后,此函数会释放数据包 */
  254.                 ret =  nx_tcp_socket_send(&TCPSocket,   
  255.                                            TraPacket,      
  256.                                             NX_WAIT_FOREVER);
  257.                
  258.                
  259.                 if (ret)
  260.                 {
  261.                     //Error_Handler(__FILE__, __LINE__);
  262.                 }
  263.                
  264.             }
  265.             else
  266.             {
  267.                 /* 释放数据包 */
  268.                 nx_packet_release(RecPacket);
  269.                
  270.                 /* 断开连接 */
  271.                 nx_tcp_socket_disconnect(&TCPSocket,
  272.                                                          NX_WAIT_FOREVER);
  273.                                
  274.                                 /* disconnect the socket */
  275.                 nx_tcp_client_socket_unbind(&TCPSocket);
  276.             }
  277.         }
  278.         }         
  279. }

  280. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码


回复

使用道具 举报

4

主题

1459

回帖

1471

积分

至尊会员

积分
1471
发表于 2021-12-27 09:37:44 | 显示全部楼层
回复

使用道具 举报

692

主题

3576

回帖

5677

积分

论坛元老

积分
5677
发表于 2021-12-27 16:44:18 | 显示全部楼层

回复

使用道具 举报

24

主题

133

回帖

205

积分

高级会员

积分
205
发表于 2021-12-30 19:45:50 来自手机 | 显示全部楼层
创建socket时最好加上断开连接回调函数,跟心跳
回复

使用道具 举报

24

主题

133

回帖

205

积分

高级会员

积分
205
发表于 2021-12-30 19:50:21 | 显示全部楼层
创建socket时加上断开连接回调,并开启断开连接通知。这样任何断开连接可以第一时间获悉。
绑定成功与否感觉可以不用断言。连接时只要是已经连接或连接成功就接续否则返回。断开连接回调需要解绑
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-15 11:17 , Processed in 0.043786 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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