【RL-TCPnet网络教程】第28章 RL-TCPnet之DNS应用

时间:2023-03-08 23:09:50
【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

第28章      RL-TCPnet之DNS应用

本章节为大家讲解RL-TCPnet的DNS应用,学习本章节前,务必要优先学习第27章的DNS基础知识。有了这些基础知识之后,再搞本章节会有事半功倍的效果。

本章教程含STM32F407开发板和STM32F429开发板。

28.1  初学者重要提示

28.2  DNS函数

28.3  DNS配置说明(Net_Config.c)

28.4  DNS调试说明(Net_Debug.c)

28.5  DNS检测过程

28.6  网络调试助手和板子的操作步骤

28.7  实验例程说明(裸机)

28.8  实验例程说明(RTX)

28.9  总结

28.1  初学者重要提示

  1. 学习本章节前,务必保证已经学习了第27章的基础知识。
  2. 本章相对比较简单,通过函数get_host_by_name实现对域名的解析,从而获得实际的IP地址。另外注意,一些大型的网站都有多个服务器的,通过此函数获取的IP地址不同,是正常的。
  3. 用户务必将网线接到能够联网的路由器或者交换机上面测试,因为DNS域名解析需要连接网络才行。

28.2  DNS函数

涉及到DNS的,仅有如下一个函数:

  • get_host_by_name

关于这个函数的讲解及其使用方法可以看教程第 3 章 3.4 小节里面说的参考资料 rlarm.chm 文件:

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

注意,这个函数不支持重入,也就是不支持多任务调用。

28.2.1  函数get_host_by_name

函数原型:

U8 get_host_by_name (

    U8* hostn,                                /* 域名指针变量 */

    void (*cbfunc)(U8 event, U8* host_ip) );  /* 回调函数 */

函数描述:

函数get_host_by_name用于获取网址的IP地址。

  1. 第1个参数是域名。
  2. 第2个参数是DNS Client的回调函数。回调函数有两个参数:
    • 回调函数第1个参数是回调消息类型:【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用
    • 回调函数第2个参数,如果解析成功的话,解析出的IP地址的缓冲区地址会保存到这个指针变量里面。
  3. 返回值有以下三种:
 【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

使用这个函数要注意以下问题:

  1. 如果用户将此函数的第1个参数填写成“192.168.1.1”等无需解析的IP地址,调用此函数后,DNS Client会立即调用此函数的回调函数。

使用举例:

 /*

 *********************************************************************************************************

 *                                          变量

 *********************************************************************************************************

 */

 char const *hosts[] =

 {

      "www.armfly.com",

      "www.baidu.com",

      "www.qq.com",

 };

 /*

 *********************************************************************************************************

 *    函 数 名: dns_cbfunc

 *    功能说明: 函数get_host_by_name的调函数。

 *    形    参: event  事件类型

 *             ip     如果事件类型是DNS_EVT_SUCCESS,此指针变量指向返回的IP地址缓冲区。

 *    返 回 值: 无

 *********************************************************************************************************

 */

 static void dns_cbfunc (unsigned char event, unsigned char *ip)

 {

      switch (event)

      {

          /* 成功解析地址 */

          case DNS_EVT_SUCCESS:

               printf_debug("%d.%d.%d.%d\n",ip[],ip[],ip[],ip[]);

               break;

          /* DNS记录数据库中不存在此地址 */

          case DNS_EVT_NONAME:

               printf_debug("Host Name does not exist in DNS record database.\n");

               break;

          /* 允许的DNS解析重试次数已经用完,仍无法解析,时间超时 */

          case DNS_EVT_TIMEOUT:

               printf_debug("DNS Resolver Timeout expired, Host Address not resolved.\n");

               break;

          /* DNS协议错误,收到无效或者被损坏的回复 */

          case DNS_EVT_ERROR:

               printf_debug("DNS Resolver Protocol Error, Host Address not resolved.\n");

               return;

      }

 }

 /*

 *********************************************************************************************************

 *    函 数 名: tcpnet_poll

 *    功能说明: 使用TCPnet必须要一直调用的函数

 *    形    参: 无

 *    返 回 值: 无

 *********************************************************************************************************

 */

 void tcpnet_poll(void)

 {

      if(bsp_CheckTimer())

      {

          bsp_LedToggle();

          /* 此函数坚决不可以放在中断里面跑 */

          timer_tick ();

      }

      main_TcpNet ();

 }

 /*

 *********************************************************************************************************

 *    函 数 名: TCPnetTest

 *    功能说明: TCPnet应用

 *    形    参: 无

 *    返 回 值: 无

 *********************************************************************************************************

 */

 void TCPnetTest(void)

 { 

      uint8_t ucKeyCode;

      /* 初始化网络协议栈 */

      init_TcpNet ();

      /* 创建一个周期是100ms的软定时器 */

     bsp_StartAutoTimer(, );

      while ()

      {

          /* TCP轮询 */

          tcpnet_poll();

          /* 按键消息的处理 */

          ucKeyCode = bsp_GetKey();

           if ((ucKeyCode != KEY_NONE))

          {

               switch (ucKeyCode)

               {

                    /* 按键K1按下,返回www.armfly.com的IP地址。 */

                    case KEY_DOWN_K1:

                        printf_debug("网址www.armfly.com的IP地址:");

                     get_host_by_name ((U8 *)hosts[], dns_cbfunc);

                        break;

                    /* 按键K2按下,返回www.baidu.com的IP地址 */

                    case KEY_DOWN_K2:

                        printf_debug("网址www.baidu.com的IP地址:");                  

                        get_host_by_name ((U8 *)hosts[], dns_cbfunc);                  

                        break;

                    /* 按键K3按下,返回www.qq.com的IP地址 */

                    case KEY_DOWN_K3:

                        printf_debug("网址www.qq.com的IP地址:");                          

                        get_host_by_name ((U8 *)hosts[], dns_cbfunc);                       

                        break;

                     /* 其他的键值不处理 */

                    default:                    

                        break;

               }

          }

      }

 }

28.3 DNS配置说明(Net_Config.c)

(本章节配套例子的配置与本小节的说明相同)

RL-TCPnet的配置工作是通过配置文件Net_Config.c实现。在MDK工程中打开文件Net_Config.c,可以看到下图所示的工程配置向导:

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

RL-TCPnet要配置的选项非常多,我们这里把几个主要的配置选项简单介绍下。

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

System Definitions

(1)Local Host Name

局域网域名。

这里起名为armfly,使用局域网域名限制为15个字符。

(2)Memory Pool size

参数范围1536-262144字节。

内存池大小配置,单位字节。另外注意一点,配置向导这里显示的单位是字节,如果看原始定义,MDK会做一个自动的4字节倍数转换,比如我们这里配置的是8192字节,那么原始定义是#define MEM_SIZE  2048,也就是8192/4 = 2048。

(3)Tick Timer interval

可取10,20,25,40,50,100,200,单位ms。

系统滴答时钟间隔,也就是网络协议栈的系统时间基准,默认情况下,取值100ms。

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

Ethernet Network Interface

以太网接口配置,勾选了此选项就可以配置了,如果没有使能DHCP的话,将使用这里配置的固定IP

(1)MAC Address

局域网内可以随意配置,只要不跟局域网内其它设备的MAC地址冲突即可。

(2)IP Address

IP地址。

(3)Subnet mask

子网掩码。

(4)Default Gateway

默认网关。

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

Ethernet Network Interface

以太网接口配置,这个配置里面还有如下两项比较重要的配置需要说明。

(1)NetBIOS Name Service

NetBIOS局域网域名服务,这里打上对勾就使能了。这样我们就可以通过前面配置的Local Host Name局域网域名进行访问,而不需要通过IP地址访问了。

(2)Dynaminc Host Configuration

即DHCP,这里打上对勾就使能了。使能了DHCP后,RL-TCPnet就可以从外接的路由器上获得动态IP地址。

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

UDP Sockets

UDP Sockets配置,打上对勾就使能了此项功能

(1)Number of UDP Sockets

用于配置可创建的UDP Sockets数量,这里配置了5个。

范围1 – 20。

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

TCP Sockets

TCP Sockets配置,打上对勾就使能了此项功能

(1)Number of TCP Sockets

用于配置可创建的TCP Sockets数量。

(2)Number of Retries

范围0-20。

用于配置重试次数,TCP数据传输时,如果在设置的重试时间内得不到应答,算一次重试失败,这里就是配置的最大重试次数。

(3)Retry Timeout in seconds

范围1-10,单位秒。

重试时间。如果发送的数据在重试时间内得不到应答,将重新发送数据。

(4)Default Connect Timeout in seconds

范围1-600,单位秒。

用于配置默认的保持连接时间,即我们常说的Keep Alive时间,如果时间到了将断开连接。常用于HTTP Server,Telnet Server等。

(5)Maximum Segment Size

范围536-1460,单位字节。

MSS定义了TCP数据包能够传输的最大数据分段。

(6)Receive Window Size

范围536-65535,单位字节。

TCP接收窗口大小。

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

DNS Client

DNS 配置,打上对勾就使能了此项功能

(1)Cache Table size

主机名/IP地址的缓存表大小。

范围5-100。

28.4 DNS调试说明(Net_Debug.c)

(重要说明,RL-TCPnet的调试是通过串口打印出来的)

RL-TCPnet的调试功能是通过配置文件Net_Debug.c实现。在MDK工程中打开文件Net_Debug.c,可以看到下图所示的工程配置向导:

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

Print Time Stamp

勾选了此选项的话,打印消息时,前面会附带时间信息。

其它所有的选项

默认情况下,所有的调试选项都关闭了,每个选项有三个调试级别可选择,这里我们以DNS Debug为例,点击下拉列表,可以看到里面有Off,Errors only和Full debug三个调试级别可供选择,每个调试选项里面都是这三个级别。

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

Off:表示关闭此选项的调试功能。

Errors only:表示仅在此选项出错时,将其错误打印出来。

Full debug:表示此选项的全功能调试。

下面是对DNS Debug配置为Full debug时,打印出来的消息(以解析网址www.armfly.com为例):

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

28.5 DNS域名解析方法

DNS的域名解析比较简单,用户仅需满足以下几个条件即可:

  • 务必记得使能Net_Config.c文件中DNS。
  • 调用函数get_host_by_name,关于这个函数的使用方法在本章的28.2.1小节有讲解。
  • 用户务必将网线接到能够联网的路由器或者交换机上面测试,因为DNS域名解析需要连接网络才行。

28.6 板子的操作步骤

本章的操作相对比较简单,用户务必将板子连接到能够联网的路由器或者交换机上。

  1. 按键K1按下,返回www.armfly.com的IP地址。
  2. 按键K2按下,返回www.baidu.com的IP地址。
  3. 按键K3按下,返回www.qq.com的IP地址。

(串口波特率115200,数据位8,奇偶校验位无,停止位1)

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

28.7 实验例程说明(裸机)

28.7.1 STM32F407开发板实验

配套例子:

V5-1036_RL-TCPnet实验_DNS应用(裸机)

实验目的:

  1. 学习RL-TCPnet的DNS使用。

实验内容:

  1. 用户务必将网线接到能够联网的路由器或者交换机上面测试,因为DNS域名解析需要连接网络才行。
  2. 像腾讯,百度等网址都有多个IP地址,如果用户测试DNS返回的地址不同,这种情况是正常的。
  3. 按键K1按下,返回www.armfly.com的IP地址。
  4. 按键K2按下,返回www.baidu.com的IP地址。
  5. 按键K3按下,返回www.qq.com的IP地址。

实验操作:

详见本章节28.6小节。

配置向导文件设置(Net_Config.c):

详见本章节28.3小节。

调试文件设置(Net_Debug.c):

详见本章节28.4小节。

程序设计:

主函数初始化

在main.c文件实现:

/*

*********************************************************************************************************

*    函 数 名: main

*    功能说明: 标准c程序入口。

*    形    参: 无

*    返 回 值: 无

*********************************************************************************************************

*/

int main (void)

{   

     /* 初始化外设 */

     bsp_Init();

     /* 进入RL-TCPnet测试函数 */

     TCPnetTest();

}

硬件外设初始化

硬件外设的初始化是在 bsp.c 文件实现:

 /*

 *********************************************************************************************************

 *    函 数 名: bsp_Init

 *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次

 *    形    参:无

 *    返 回 值: 无

 *********************************************************************************************************

 */

 void bsp_Init(void)

 {

      /*

          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。

          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。

          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件

      */

      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/

      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

      bsp_InitUart();    /* 初始化串口 */

      bsp_InitKey();     /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */

      bsp_InitLed();     /* 初始LED指示灯端口 */

      bsp_InitTimer();   /* 初始化滴答定时器 */

 }

RL-TCPnet功能测试

这里专门创建了一个app_tcpnet_lib.c文件用于RL-TCPnet功能的测试,这里通过函数get_host_by_name来解析网址对应的IP地址。

 /*

 *********************************************************************************************************

 *                                      用于本文件的调试

 *********************************************************************************************************

 */

 #if 1

      #define printf_debug printf

 #else

      #define printf_debug(...)

 #endif

 /*

 *********************************************************************************************************

 *                                          变量

 *********************************************************************************************************

 */

 char const *hosts[] =

 {

      "www.armfly.com",

      "www.baidu.com",

      "www.qq.com",

 };

 /*

 *********************************************************************************************************

 *    函 数 名: dns_cbfunc

 *    功能说明: 函数get_host_by_name的调函数。

 *    形    参: event  事件类型

 *             ip     如果事件类型是DNS_EVT_SUCCESS,此指针变量指向返回的IP地址缓冲区。

 *    返 回 值: 无

 *********************************************************************************************************

 */

 static void dns_cbfunc (unsigned char event, unsigned char *ip)

 {

      switch (event)

      {

          /* 成功解析地址 */

          case DNS_EVT_SUCCESS:

               printf_debug("%d.%d.%d.%d\n",ip[],ip[],ip[],ip[]);

               break;

          /* DNS记录数据库中不存在此地址 */

          case DNS_EVT_NONAME:

               printf_debug("Host Name does not exist in DNS record database.\n");

               break;

          /* 允许的DNS解析重试次数已经用完,仍无法解析,时间超时 */

          case DNS_EVT_TIMEOUT:

               printf_debug("DNS Resolver Timeout expired, Host Address not resolved.\n");

               break;

           /* DNS协议错误,收到无效或者被损坏的回复 */

          case DNS_EVT_ERROR:

               printf_debug("DNS Resolver Protocol Error, Host Address not resolved.\n");

               return;

      }

 }

 /*

 *********************************************************************************************************

 *    函 数 名: tcpnet_poll

 *    功能说明: 使用TCPnet必须要一直调用的函数

 *    形    参: 无

 *    返 回 值: 无

 *********************************************************************************************************

 */

 void tcpnet_poll(void)

 {

      if(bsp_CheckTimer())

      {

          /* 此函数坚决不可以放在中断里面跑 */

          timer_tick ();

      }

      main_TcpNet ();

 }

 /*

 *********************************************************************************************************

 *    函 数 名: TCPnetTest

 *    功能说明: TCPnet应用

 *    形    参: 无

 *    返 回 值: 无

 *********************************************************************************************************

 */

 void TCPnetTest(void)

 { 

      uint8_t ucKeyCode;

      /* 初始化网络协议栈 */

      init_TcpNet ();

      /* 创建一个周期是100ms的软定时器 */

     bsp_StartAutoTimer(, );

      while ()

      {

           /* TCP轮询 */

          tcpnet_poll();

           /* 按键消息的处理 */

          ucKeyCode = bsp_GetKey();

          if ((ucKeyCode != KEY_NONE))

          {

               switch (ucKeyCode)

               {

                    /* 按键K1按下,返回www.armfly.com的IP地址。 */

                    case KEY_DOWN_K1:

                        printf_debug("网址www.armfly.com的IP地址:");

                        get_host_by_name ((U8 *)hosts[], dns_cbfunc);

                        break;

                    /* 按键K2按下,返回www.baidu.com的IP地址 */

                    case KEY_DOWN_K2:

                        printf_debug("网址www.baidu.com的IP地址:");                  

                         get_host_by_name ((U8 *)hosts[], dns_cbfunc);                  

                        break;

                    /* 按键K3按下,返回www.qq.com的IP地址 */

                    case KEY_DOWN_K3:

                        printf_debug("网址www.qq.com的IP地址:");                          

                        get_host_by_name ((U8 *)hosts[], dns_cbfunc);                       

                        break;

                     /* 其他的键值不处理 */

                    default:                    

                        break;

               }

          }

      }

 }

28.7.2 STM32F429开发板实验

配套例子:

V6-1036_RL-TCPnet实验_DNS应用(裸机)

实验目的:

  1. 学习RL-TCPnet的DNS使用。

实验内容:

  1. 用户务必将网线接到能够联网的路由器或者交换机上面测试,因为DNS域名解析需要连接网络才行。
  2. 像腾讯,百度等网址都有多个IP地址,如果用户测试DNS返回的地址不同,这种情况是正常的。
  3. 按键K1按下,返回www.armfly.com的IP地址。
  4. 按键K2按下,返回www.baidu.com的IP地址。
  5. 按键K3按下,返回www.qq.com的IP地址。

实验操作:

详见本章节28.6小节。

配置向导文件设置(Net_Config.c):

详见本章节28.3小节。

调试文件设置(Net_Debug.c):

详见本章节28.4小节。

程序设计:

主函数初始化

在main.c文件实现:

/*

*********************************************************************************************************

*    函 数 名: main

*    功能说明: 标准c程序入口。

*    形    参: 无

*    返 回 值: 无

*********************************************************************************************************

*/

int main (void)

{   

     /* 初始化外设 */

     bsp_Init();

     /* 进入RL-TCPnet测试函数 */

     TCPnetTest();

}

硬件外设初始化

硬件外设的初始化是在 bsp.c 文件实现:

 /*

 *********************************************************************************************************

 *    函 数 名: bsp_Init

 *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次

 *    形    参:无

 *    返 回 值: 无

 *********************************************************************************************************

 */

 void bsp_Init(void)

 {

      /*

          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。

          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。

          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件

      */

      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/

      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

      bsp_InitUart();    /* 初始化串口 */

      bsp_InitKey();     /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */

      bsp_InitLed();     /* 初始LED指示灯端口 */

      bsp_InitTimer();   /* 初始化滴答定时器 */

 }

RL-TCPnet功能测试

这里专门创建了一个app_tcpnet_lib.c文件用于RL-TCPnet功能的测试,这里通过函数get_host_by_name来解析网址对应的IP地址。

/*

*********************************************************************************************************

*                                      用于本文件的调试

*********************************************************************************************************

*/

#if 1

     #define printf_debug printf

#else

     #define printf_debug(...)

#endif

/*

*********************************************************************************************************

*                                          变量

*********************************************************************************************************

*/

char const *hosts[] =

{

     "www.armfly.com",

     "www.baidu.com",

     "www.qq.com",

};

/*

*********************************************************************************************************

*    函 数 名: dns_cbfunc

*    功能说明: 函数get_host_by_name的调函数。

*    形    参: event  事件类型

*             ip     如果事件类型是DNS_EVT_SUCCESS,此指针变量指向返回的IP地址缓冲区。

*    返 回 值: 无

*********************************************************************************************************

*/

static void dns_cbfunc (unsigned char event, unsigned char *ip)

{

     switch (event)

     {

         /* 成功解析地址 */

         case DNS_EVT_SUCCESS:

              printf_debug("%d.%d.%d.%d\n",ip[],ip[],ip[],ip[]);

              break;

         /* DNS记录数据库中不存在此地址 */

         case DNS_EVT_NONAME:

              printf_debug("Host Name does not exist in DNS record database.\n");

              break;

         /* 允许的DNS解析重试次数已经用完,仍无法解析,时间超时 */

         case DNS_EVT_TIMEOUT:

              printf_debug("DNS Resolver Timeout expired, Host Address not resolved.\n");

              break;

          /* DNS协议错误,收到无效或者被损坏的回复 */

         case DNS_EVT_ERROR:

              printf_debug("DNS Resolver Protocol Error, Host Address not resolved.\n");

              return;

     }

}

/*

*********************************************************************************************************

*    函 数 名: tcpnet_poll

*    功能说明: 使用TCPnet必须要一直调用的函数

*    形    参: 无

*    返 回 值: 无

*********************************************************************************************************

*/

void tcpnet_poll(void)

{

     if(bsp_CheckTimer())

     {

         /* 此函数坚决不可以放在中断里面跑 */

         timer_tick ();

     }

     main_TcpNet ();

}

/*

*********************************************************************************************************

*    函 数 名: TCPnetTest

*    功能说明: TCPnet应用

*    形    参: 无

*    返 回 值: 无

*********************************************************************************************************

*/

void TCPnetTest(void)

{ 

     uint8_t ucKeyCode;

     /* 初始化网络协议栈 */

     init_TcpNet ();

     /* 创建一个周期是100ms的软定时器 */

    bsp_StartAutoTimer(, );

     while ()

     {

          /* TCP轮询 */

         tcpnet_poll();

          /* 按键消息的处理 */

         ucKeyCode = bsp_GetKey();

          if ((ucKeyCode != KEY_NONE))

         {

              switch (ucKeyCode)

              {

                   /* 按键K1按下,返回www.armfly.com的IP地址。 */

                   case KEY_DOWN_K1:

                       printf_debug("网址www.armfly.com的IP地址:");

                       get_host_by_name ((U8 *)hosts[], dns_cbfunc);

                       break;

                   /* 按键K2按下,返回www.baidu.com的IP地址 */

                   case KEY_DOWN_K2:

                       printf_debug("网址www.baidu.com的IP地址:");                  

                       get_host_by_name ((U8 *)hosts[], dns_cbfunc);                  

                       break;

                   /* 按键K3按下,返回www.qq.com的IP地址 */

                   case KEY_DOWN_K3:

                       printf_debug("网址www.qq.com的IP地址:");                          

                       get_host_by_name ((U8 *)hosts[], dns_cbfunc);                       

                       break;

                    /* 其他的键值不处理 */

                   default:                    

                       break;

              }

         }

     }

}

28.8 实验例程说明(RTX)

28.8.1 STM32F407开发板实验

配套例子:

V5-1037_RL-TCPnet实验_DNS应用(RTX)

实验目的:

  1. 学习RL-TCPnet的DNS使用。

实验内容:

  1. 用户务必将网线接到能够联网的路由器或者交换机上面测试,因为DNS域名解析需要连接网络才行。
  2. 像腾讯,百度等网址都有多个IP地址,如果用户测试DNS返回的地址不同,这种情况是正常的。
  3. 按键K1按下,返回www.armfly.com的IP地址。
  4. 按键K2按下,返回www.baidu.com的IP地址。
  5. 按键K3按下,返回www.qq.com的IP地址。

实验操作:

详见本章节28.6小节。

配置向导文件设置(Net_Config.c):

详见本章节28.3小节。

调试文件设置(Net_Debug.c):

详见本章节28.4小节。

RTX配置:

RTX配置向导详情如下:

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

Task Configuration

(1)Number of concurrent running tasks

允许创建6个任务,实际创建了如下5个任务:

AppTaskUserIF任务   :按键消息处理。

AppTaskLED任务     :LED闪烁。

AppTaskMsgPro任务 :按键检测。

AppTaskTCPMain任务:RL-TCPnet测试任务。

AppTaskStart任务  :启动任务,也是最高优先级任务,这里实现RL-TCPnet的时间基准更新。

(2)Number of tasks with user-provided stack

创建的5个任务都是采用自定义堆栈方式。

(3)Run in privileged mode

设置任务运行在非特权级模式。

RTX任务调试信息:

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

程序设计:

任务栈大小分配:

static uint64_t AppTaskUserIFStk[1024/8];   /* 任务栈 */

static uint64_t AppTaskLEDStk[1024/8];      /* 任务栈 */

static uint64_t AppTaskMsgProStk[1024/8];  /* 任务栈 */

static uint64_t AppTaskTCPMainStk[2048/8]; /* 任务栈 */

static uint64_t AppTaskStartStk[1024/8];     /* 任务栈 */

将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数、浮点运算和uint64_t类型数据运算会出问题。

系统栈大小分配:

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

RTX初始化:

/*

*********************************************************************************************************

*    函 数 名: main

*    功能说明: 标准c程序入口。

*    形    参: 无

*    返 回 值: 无

*********************************************************************************************************

*/

int main (void)

{   

     /* 初始化外设 */

     bsp_Init();

     /* 创建启动任务 */

     os_sys_init_user (AppTaskStart,              /* 任务函数 */

                       ,                         /* 任务优先级 */

                       &AppTaskStartStk,          /* 任务栈 */

                       sizeof(AppTaskStartStk));  /* 任务栈大小,单位字节数 */

     while();

}

硬件外设初始化

硬件外设的初始化是在 bsp.c 文件实现:

 /*

 *********************************************************************************************************

 *    函 数 名: bsp_Init

 *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次

 *    形    参:无

 *    返 回 值: 无

 *********************************************************************************************************

 */

 void bsp_Init(void)

 {

      /*

          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。

          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。

          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件

      */

      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/

      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

      bsp_InitDWT();     /* 初始化DWT */

      bsp_InitUart();    /* 初始化串口 */

      bsp_InitKey();    /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */

      bsp_InitLed();    /* 初始LED指示灯端口 */

 }

RTX任务创建:

 /*

 *********************************************************************************************************

 *    函 数 名: AppTaskCreate

 *    功能说明: 创建应用任务

 *    形    参: 无

 *    返 回 值: 无

 *********************************************************************************************************

 */

 static void AppTaskCreate (void)

 {

      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */

                                            ,                         /* 任务优先级 */

                                            &AppTaskUserIFStk,         /* 任务栈 */

                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */

      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */

                                         ,                       /* 任务优先级 */

                                         &AppTaskLEDStk,          /* 任务栈 */

                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */

      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */

                                            ,                         /* 任务优先级 */

                                            &AppTaskMsgProStk,         /* 任务栈 */

                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */

     HandleTaskTCPMain = os_tsk_create_user(AppTaskTCPMain,             /* 任务函数 */

                                            ,                         /* 任务优先级 */

                                            &AppTaskTCPMainStk,         /* 任务栈 */

                                            sizeof(AppTaskTCPMainStk)); /* 任务栈大小,单位字节数 */

 }

五个RTX任务的实现:

 /*

 *********************************************************************************************************

 *    函 数 名: AppTaskUserIF

 *    功能说明: 按键消息处理     

 *    形    参: 无

 *    返 回 值: 无

 *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)

 *********************************************************************************************************

 */

 __task void AppTaskUserIF(void)

 {

      uint8_t ucKeyCode;

     while()

     {

          ucKeyCode = bsp_GetKey();

          if (ucKeyCode != KEY_NONE)

          {

               switch (ucKeyCode)

               {

                    /* K1键按下,直接发送事件标志给任务AppTaskTCPMain,设置bit0 */

                    case KEY_DOWN_K1:

                        printf("K1键按下,直接发送事件标志给任务AppTaskTCPMain,bit0被设置\r\n");

                        os_evt_set (KEY1_BIT0, HandleTaskTCPMain);                      

                        break;  

                    /* K2键按下,直接发送事件标志给任务AppTaskTCPMain,设置bit1 */

                    case KEY_DOWN_K2:

                        printf("K2键按下,直接发送事件标志给任务AppTaskTCPMain,bit1被设置\r\n");

                        os_evt_set (KEY2_BIT1, HandleTaskTCPMain);

                        break;

                    /* K3键按下,直接发送事件标志给任务AppTaskTCPMain,设置bit2 */

                    case KEY_DOWN_K3:

                        printf("K3键按下,直接发送事件标志给任务AppTaskTCPMain,bit2被设置\r\n");

                        os_evt_set (KEY3_BIT2, HandleTaskTCPMain);

                        break;

                    /* 其他的键值不处理 */

                    default:                    

                        break;

               }

          }

          os_dly_wait();

      }

 }

 /*

 *********************************************************************************************************

 *    函 数 名: AppTaskLED

 *    功能说明: LED闪烁。

 *    形    参: 无

 *    返 回 值: 无

 *   优 先 级: 2 

 *********************************************************************************************************

 */

 __task void AppTaskLED(void)

 {

      const uint16_t usFrequency = ; /* 延迟周期 */

      /* 设置延迟周期 */

      os_itv_set(usFrequency);

     while()

     {

          bsp_LedToggle();

          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/

          os_itv_wait();

     }

 }

 /*

 *********************************************************************************************************

 *    函 数 名: AppTaskMsgPro

 *    功能说明: 按键检测

 *    形    参: 无

 *    返 回 值: 无

 *   优 先 级: 3 

 *********************************************************************************************************

 */

 __task void AppTaskMsgPro(void)

 {

     while()

     {

          bsp_KeyScan();

          os_dly_wait();

     }

 }

 /*

 *********************************************************************************************************

 *    函 数 名: AppTaskTCPMain

 *    功能说明: RL-TCPnet测试任务

 *    形    参: 无

 *    返 回 值: 无

 *   优 先 级: 4 

 *********************************************************************************************************

 */

 __task void AppTaskTCPMain(void)

 {

      while ()

      {

          TCPnetTest();

      }

 }

 /*

 *********************************************************************************************************

 *    函 数 名: AppTaskStart

 *    功能说明: 启动任务,也是最高优先级任务,这里实现RL-TCPnet的时间基准更新。

 *    形    参: 无

 *    返 回 值: 无

 *   优 先 级: 5 

 *********************************************************************************************************

 */

 __task void AppTaskStart(void)

 {

      /* 初始化RL-TCPnet */

      init_TcpNet ();

      /* 创建任务 */

      AppTaskCreate();

      os_itv_set ();

     while()

     {

          os_itv_wait ();

          /* RL-TCPnet时间基准更新函数 */

          timer_tick ();

     }

 }

RL-TCPnet功能测试

这里专门创建了一个app_tcpnet_lib.c文件用于RL-TCPnet功能的测试,这里通过函数get_host_by_name来解析网址对应的IP地址。

 #include "includes.h" 

 /*

 *********************************************************************************************************

 *                                      用于本文件的调试

 *********************************************************************************************************

 */

 #if 1

      #define printf_debug printf

 #else

      #define printf_debug(...)

 #endif

 /*

 *********************************************************************************************************

 *                                          变量

 *********************************************************************************************************

 */

 char const *hosts[] =

 {

      "www.armfly.com",

      "www.baidu.com",

      "www.qq.com",

 };

 /*

 *********************************************************************************************************

 *    函 数 名: dns_cbfunc

 *    功能说明: 函数get_host_by_name的调函数。

 *    形    参: event  事件类型

 *             ip     如果事件类型是DNS_EVT_SUCCESS,此指针变量指向返回的IP地址缓冲区。

 *    返 回 值: 无

 *********************************************************************************************************

 */

 static void dns_cbfunc (unsigned char event, unsigned char *ip)

 {

      switch (event)

      {

          /* 成功解析地址 */

          case DNS_EVT_SUCCESS:

               printf_debug("%d.%d.%d.%d\n",ip[],ip[],ip[],ip[]);

               break;

          /* DNS记录数据库中不存在此地址 */

          case DNS_EVT_NONAME:

               printf_debug("Host Name does not exist in DNS record database.\n");

               break;

          /* 允许的DNS解析重试次数已经用完,仍无法解析,时间超时 */

          case DNS_EVT_TIMEOUT:

               printf_debug("DNS Resolver Timeout expired, Host Address not resolved.\n");

               break;

          /* DNS协议错误,收到无效或者被损坏的回复 */

          case DNS_EVT_ERROR:

               printf_debug("DNS Resolver Protocol Error, Host Address not resolved.\n");

               return;

      }

 }

 /*

 *********************************************************************************************************

 *    函 数 名: TCPnetTest

 *    功能说明: TCPnet应用

 *    形    参: 无

 *    返 回 值: 无

 *********************************************************************************************************

 */

 void TCPnetTest(void)

 { 

      OS_RESULT xResult;

      const uint16_t usMaxBlockTime = ; /* 延迟周期 */

      while ()

      {

          /* RL-TCPnet处理函数 */

          main_TcpNet();

           /* 按键消息的处理 */

          if(os_evt_wait_or(0xFFFF, usMaxBlockTime) == OS_R_EVT)

          {

               xResult = os_evt_get ();

               switch (xResult)

               {

                    /* 接收到按键K1按下消息,返回www.armfly.com的IP地址。 */

                    case KEY1_BIT0:

                        printf_debug("网址www.armfly.com的IP地址:");

                     get_host_by_name ((U8 *)hosts[], dns_cbfunc);                 

                        break;

                    /* 接收到K2键按下消息,返回www.baidu.com的IP地址 */

                    case KEY2_BIT1:   

                        printf_debug("网址www.baidu.com的IP地址:");                  

                        get_host_by_name ((U8 *)hosts[], dns_cbfunc);

                        break;

                    /* 接收到K3键按下消息,返回www.qq.com的IP地址 */

                    case KEY3_BIT2:

                        printf_debug("网址www.qq.com的IP地址:");                          

                         get_host_by_name ((U8 *)hosts[], dns_cbfunc);         

                        break;

                     /* 其他的键值不处理 */

                    default:                    

                        break;

               }

          }

      }

 }

28.8.2 STM32F429开发板实验

配套例子:

V6-1037_RL-TCPnet实验_DNS应用(RTX)

实验目的:

  1. 学习RL-TCPnet的DNS使用。

实验内容:

  1. 用户务必将网线接到能够联网的路由器或者交换机上面测试,因为DNS域名解析需要连接网络才行。
  2. 像腾讯,百度等网址都有多个IP地址,如果用户测试DNS返回的地址不同,这种情况是正常的。
  3. 按键K1按下,返回www.armfly.com的IP地址。
  4. 按键K2按下,返回www.baidu.com的IP地址。
  5. 按键K3按下,返回www.qq.com的IP地址。

实验操作:

详见本章节28.6小节。

配置向导文件设置(Net_Config.c):

详见本章节28.3小节。

调试文件设置(Net_Debug.c):

详见本章节28.4小节。

RTX配置:

RTX配置向导详情如下:

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

Task Configuration

(1)Number of concurrent running tasks

允许创建6个任务,实际创建了如下5个任务:

AppTaskUserIF任务   :按键消息处理。

AppTaskLED任务     :LED闪烁。

AppTaskMsgPro任务 :按键检测。

AppTaskTCPMain任务:RL-TCPnet测试任务。

AppTaskStart任务  :启动任务,也是最高优先级任务,这里实现RL-TCPnet的时间基准更新。

(2)Number of tasks with user-provided stack

创建的5个任务都是采用自定义堆栈方式。

(3)Run in privileged mode

设置任务运行在非特权级模式。

RTX任务调试信息:

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

程序设计:

任务栈大小分配:

static uint64_t AppTaskUserIFStk[1024/8];   /* 任务栈 */

static uint64_t AppTaskLEDStk[1024/8];      /* 任务栈 */

static uint64_t AppTaskMsgProStk[1024/8];  /* 任务栈 */

static uint64_t AppTaskTCPMainStk[2048/8]; /* 任务栈 */

static uint64_t AppTaskStartStk[1024/8];     /* 任务栈 */

将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数、浮点运算和uint64_t类型数据运算会出问题。

系统栈大小分配:

【RL-TCPnet网络教程】第28章    RL-TCPnet之DNS应用

RTX初始化:

/*

*********************************************************************************************************

*    函 数 名: main

*    功能说明: 标准c程序入口。

*    形    参: 无

*    返 回 值: 无

*********************************************************************************************************

*/

int main (void)

{   

     /* 初始化外设 */

     bsp_Init();

     /* 创建启动任务 */

     os_sys_init_user (AppTaskStart,              /* 任务函数 */

                       ,                         /* 任务优先级 */

                       &AppTaskStartStk,          /* 任务栈 */

                       sizeof(AppTaskStartStk));  /* 任务栈大小,单位字节数 */

     while();

}

硬件外设初始化

硬件外设的初始化是在 bsp.c 文件实现:

 /*

 *********************************************************************************************************

 *    函 数 名: bsp_Init

 *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次

 *    形    参:无

 *    返 回 值: 无

 *********************************************************************************************************

 */

 void bsp_Init(void)

 {

      /*

          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。

          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。

          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件

      */

      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/

      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

      SystemCoreClockUpdate();    /* 根据PLL配置更新系统时钟频率变量 SystemCoreClock */

      bsp_InitDWT();      /* 初始化DWT */

      bsp_InitUart();     /* 初始化串口 */

      bsp_InitKey();     /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */

      bsp_InitExtIO();    /* FMC总线上扩展了32位输出IO, 操作LED等外设必须初始化 */

      bsp_InitLed();      /* 初始LED指示灯端口 */

 }

RTX任务创建:

 /*

 *********************************************************************************************************

 *    函 数 名: AppTaskCreate

 *    功能说明: 创建应用任务

 *    形    参: 无

 *    返 回 值: 无

 *********************************************************************************************************

 */

 static void AppTaskCreate (void)

 {

      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */

                                            ,                         /* 任务优先级 */

                                            &AppTaskUserIFStk,         /* 任务栈 */

                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */

      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */

                                         ,                       /* 任务优先级 */

                                         &AppTaskLEDStk,          /* 任务栈 */

                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */

      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */

                                            ,                         /* 任务优先级 */

                                            &AppTaskMsgProStk,         /* 任务栈 */

                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */

     HandleTaskTCPMain = os_tsk_create_user(AppTaskTCPMain,             /* 任务函数 */

                                            ,                         /* 任务优先级 */

                                            &AppTaskTCPMainStk,         /* 任务栈 */

                                            sizeof(AppTaskTCPMainStk)); /* 任务栈大小,单位字节数 */

 }

五个RTX任务的实现:

 /*

 *********************************************************************************************************

 *    函 数 名: AppTaskUserIF

 *    功能说明: 按键消息处理     

 *    形    参: 无

 *    返 回 值: 无

 *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)

 *********************************************************************************************************

 */

 __task void AppTaskUserIF(void)

 {

      uint8_t ucKeyCode;

     while()

     {

          ucKeyCode = bsp_GetKey();

          if (ucKeyCode != KEY_NONE)

          {

               switch (ucKeyCode)

               {

                    /* K1键按下,直接发送事件标志给任务AppTaskTCPMain,设置bit0 */

                    case KEY_DOWN_K1:

                        printf("K1键按下,直接发送事件标志给任务AppTaskTCPMain,bit0被设置\r\n");

                        os_evt_set (KEY1_BIT0, HandleTaskTCPMain);                      

                        break;  

                    /* K2键按下,直接发送事件标志给任务AppTaskTCPMain,设置bit1 */

                    case KEY_DOWN_K2:

                        printf("K2键按下,直接发送事件标志给任务AppTaskTCPMain,bit1被设置\r\n");

                        os_evt_set (KEY2_BIT1, HandleTaskTCPMain);

                        break;

                    /* K3键按下,直接发送事件标志给任务AppTaskTCPMain,设置bit2 */

                    case KEY_DOWN_K3:

                        printf("K3键按下,直接发送事件标志给任务AppTaskTCPMain,bit2被设置\r\n");

                        os_evt_set (KEY3_BIT2, HandleTaskTCPMain);

                        break;

                    /* 其他的键值不处理 */

                    default:                    

                        break;

               }

          }

          os_dly_wait();

      }

 }

 /*

 *********************************************************************************************************

 *    函 数 名: AppTaskLED

 *    功能说明: LED闪烁。

 *    形    参: 无

 *    返 回 值: 无

 *   优 先 级: 2 

 *********************************************************************************************************

 */

 __task void AppTaskLED(void)

 {

      const uint16_t usFrequency = ; /* 延迟周期 */

      /* 设置延迟周期 */

      os_itv_set(usFrequency);

     while()

     {

          bsp_LedToggle();

          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/

          os_itv_wait();

     }

 }

 /*

 *********************************************************************************************************

 *    函 数 名: AppTaskMsgPro

 *    功能说明: 按键检测

 *    形    参: 无

 *    返 回 值: 无

 *   优 先 级: 3 

 *********************************************************************************************************

 */

 __task void AppTaskMsgPro(void)

 {

     while()

     {

          bsp_KeyScan();

          os_dly_wait();

     }

 }

 /*

 *********************************************************************************************************

 *    函 数 名: AppTaskTCPMain

 *    功能说明: RL-TCPnet测试任务

 *    形    参: 无

 *    返 回 值: 无

 *   优 先 级: 4 

 *********************************************************************************************************

 */

 __task void AppTaskTCPMain(void)

 {

      while ()

      {

          TCPnetTest();

      }

 }

 /*

 *********************************************************************************************************

 *    函 数 名: AppTaskStart

 *    功能说明: 启动任务,也是最高优先级任务,这里实现RL-TCPnet的时间基准更新。

 *    形    参: 无

 *    返 回 值: 无

 *   优 先 级: 5 

 *********************************************************************************************************

 */

 __task void AppTaskStart(void)

 {

      /* 初始化RL-TCPnet */

      init_TcpNet ();

      /* 创建任务 */

      AppTaskCreate();

      os_itv_set ();

     while()

     {

          os_itv_wait ();

          /* RL-TCPnet时间基准更新函数 */

           timer_tick ();

     }

 }

RL-TCPnet功能测试

这里专门创建了一个app_tcpnet_lib.c文件用于RL-TCPnet功能的测试,这里通过函数get_host_by_name来解析网址对应的IP地址。

 #include "includes.h" 

 /*

 *********************************************************************************************************

 *                                      用于本文件的调试

 *********************************************************************************************************

 */

 #if 1

      #define printf_debug printf

 #else

      #define printf_debug(...)

 #endif

 /*

 *********************************************************************************************************

 *                                          变量

 *********************************************************************************************************

 */

 char const *hosts[] =

 {

      "www.armfly.com",

      "www.baidu.com",

      "www.qq.com",

 };

 /*

 *********************************************************************************************************

 *    函 数 名: dns_cbfunc

 *    功能说明: 函数get_host_by_name的调函数。

 *    形    参: event  事件类型

 *             ip     如果事件类型是DNS_EVT_SUCCESS,此指针变量指向返回的IP地址缓冲区。

 *    返 回 值: 无

 *********************************************************************************************************

 */

 static void dns_cbfunc (unsigned char event, unsigned char *ip)

 {

      switch (event)

      {

          /* 成功解析地址 */

          case DNS_EVT_SUCCESS:

               printf_debug("%d.%d.%d.%d\n",ip[],ip[],ip[],ip[]);

               break;

          /* DNS记录数据库中不存在此地址 */

          case DNS_EVT_NONAME:

               printf_debug("Host Name does not exist in DNS record database.\n");

               break;

          /* 允许的DNS解析重试次数已经用完,仍无法解析,时间超时 */

          case DNS_EVT_TIMEOUT:

               printf_debug("DNS Resolver Timeout expired, Host Address not resolved.\n");

               break;

          /* DNS协议错误,收到无效或者被损坏的回复 */

          case DNS_EVT_ERROR:

               printf_debug("DNS Resolver Protocol Error, Host Address not resolved.\n");

               return;

      }

 }

 /*

 *********************************************************************************************************

 *    函 数 名: TCPnetTest

 *    功能说明: TCPnet应用

 *    形    参: 无

 *    返 回 值: 无

 *********************************************************************************************************

 */

 void TCPnetTest(void)

 { 

      OS_RESULT xResult;

      const uint16_t usMaxBlockTime = ; /* 延迟周期 */

      while ()

      {

          /* RL-TCPnet处理函数 */

          main_TcpNet();

           /* 按键消息的处理 */

          if(os_evt_wait_or(0xFFFF, usMaxBlockTime) == OS_R_EVT)

          {

               xResult = os_evt_get ();

               switch (xResult)

               {

                    /* 接收到按键K1按下消息,返回www.armfly.com的IP地址。 */

                    case KEY1_BIT0:

                        printf_debug("网址www.armfly.com的IP地址:");

                     get_host_by_name ((U8 *)hosts[], dns_cbfunc);                 

                        break;

                    /* 接收到K2键按下消息,返回www.baidu.com的IP地址 */

                    case KEY2_BIT1:   

                        printf_debug("网址www.baidu.com的IP地址:");                  

                        get_host_by_name ((U8 *)hosts[], dns_cbfunc);

                        break;

                    /* 接收到K3键按下消息,返回www.qq.com的IP地址 */

                    case KEY3_BIT2:

                        printf_debug("网址www.qq.com的IP地址:");                          

                        get_host_by_name ((U8 *)hosts[], dns_cbfunc);         

                        break;

                     /* 其他的键值不处理 */

                    default:                    

                        break;

               }

          }

      }

 }

28.9 总结

本章节就为大家讲解这么多,内容相对比较简单,主要是函数get_host_by_name的使用,希望大家熟练掌握。