tag 标签: keepalive

相关博文
  • 热度 33
    2015-5-6 14:24
    2624 次阅读|
    0 个评论
    在使用 W5200 和 W5500 的 TCP 通信过程中,有一个非常容易被问到的问题: (这里以 W5200 为例) W5200 作为服务器,假如客户端的网线断开   或   瞬间停电,服务器该怎样判断? 那么当客户端由于这些原因忽然断开,该怎样解决? 今天给大家介绍解决以上问题的办法,即如何使用 Keepalive 。 什么是 Keepalive ? Keepalive 即心跳检测,以下简称 KA ,之所以称之为心跳检测是因为它像心跳一样每隔一段时间发一次,以此来告诉对方自己是否存活。心跳检测用于 TCP 通讯过程中服务器检测客户端是处于长时间空闲(在线)还是已经断开,一般采用客户端定时发送简单的通讯包,一般是很小的包或者空包给服务器( W5200 的心跳包为 1 字节),如果在指定时间内没有收到该心跳包,则服务器会判断客户端已经断开,此时程序中的 Socket 状态机会转到 SOCKET_CLOSED 并重新打开 Socket 去连接服务器 / 监听客户端。 KeepAlive 怎么分类?        KA 根据发出方不同可以分为两种,一种是由客户端发给服务器的心跳包,一种是服务器发给客户端的心跳包,选择哪一种方式需要看哪一方实现起来方便合理。需要注意的是, W5200 根据合理的设计,其心跳包需要在 Socket TCP 连接建立之后,服务器和客户端至少进行一次数据交互,且在设定的时间内没有数据交互时发出。 W5200 KA 程序说明        下面我以 W5200 的 TCP Server 官方例程为例,用 PC 建立 TCP 客户端来连接 W5200 ,说明 KA 的实现方法。 定义和初始化部分: 程序中用到了定时器和中断函数,在 w5200_config.c 中做了定义:   void Timer_Configuration(void) {   TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);   TIM_TimeBaseStructure.TIM_Period = 1000;             TIM_TimeBaseStructure.TIM_Prescaler = 0;         TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;       TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   TIM_TimeBaseInit(TIM2, TIM_TimeBaseStructure);     TIM_PrescalerConfig(TIM2, 71, TIM_PSCReloadMode_Immediate);     TIM_Cmd(TIM2, ENABLE);   TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); void Timer2_ISR(void) {   ms++;                                                                   // 等待时间自增,单位为 ms   if((ms % 1000)==0)                                               // 当等待时间增加到某一秒   {     if(ka_tick_flag==1)ka_no_data_tick++;                  // 若 KA 定时器标志位为 1 ,无数据传输 时间计时器自增     if(ka_no_data_tick=NO_DATA_PERIOD)                  {    ka_send_tick++;                                // 当无数据传输时间计时器值大于 NO_DATA_PERIOD , KA 发送定时器开始自增     if(ka_send_tick=KA_SEND_PERIOD)       {         ka_sen       d_flag=1;                            / / 当 KA 发送定时器的大于 KA_SEND_PERIOD , KA 发送标志位置 1 ,发送一个 KA 包       }     }         printf(".");                             // 当时间没到整秒,发一个“ . ”   } }   在主程序中进行初始化: Timer_Configuration();                       // 定时器初始化 NVIC_Configuration();                        // 中断函数初始化   程序中定义了 ka_tick_flag ( KA 定时器开始计时标志位)、 ka_send_flag ( KA 发送标志位)、 ka_no_data_tick ( KA 无数据传输时间计时器)以及 ka_send_tick ( KA 发送定时器)。在 w5200_config.c 中对以上定义进行了初始化: uint32 ka_no_data_tick=0;                                   // 定义无数据传输时间计时器 uint8 ka_tick_flag=0;                                            // 定义 KA 定时器开始计时标志位 uint32 ka_send_tick=0;                                         // 定义 KA 发送定时器 uint8 ka_send_flag=0;                                           // 定义 KA 发送标志位 主循环部分: 当程序烧录后,按 Reset 键重启 W5200 后服务器打开一个 Socket ,此时 Socket 由 SOCK_CLOSED 变为 SOCK_INIT 并处于监听状态。 PC 建立客户端成功连接 W5200 后, Socket 处于 SOCK_ESTABLISHED ,下面是程序具体的操作过程:   case SOCK_ESTABLISHED:                                                        // Socket 处于连接建立状态 if(getSn_IR(0) Sn_IR_CON)          {            setSn_IR(0, Sn_IR_CON);                                             // Sn_IR 的第 0 位置 1            ka_tick_flag=0;                                                            // KA 定时器开始计时标志位清零 继续阅读: http://www.iwiznet.cn/blog/?p=7124  
  • 热度 23
    2015-5-6 14:18
    3029 次阅读|
    0 个评论
    在使用 W5200 和 W5500 的 TCP 通信过程中,有一个非常容易被问到的问题: (这里以 W5200 为例) W5200 作为服务器,假如客户端的网线断开   或   瞬间停电,服务器该怎样判断? 那么当客户端由于这些原因忽然断开,该怎样解决? 今天给大家介绍解决以上问题的办法,即如何使用 Keepalive 。   什么是 Keepalive ?   Keepalive 即心跳检测,以下简称 KA ,之所以称之为心跳检测是因为它像心跳一样每隔一段时间发一次,以此来告诉对方自己是否存活。心跳检测用于 TCP 通讯过程中服务器检测客户端是处于长时间空闲(在线)还是已经断开,一般采用客户端定时发送简单的通讯包,一般是很小的包或者空包给服务器( W5200 的心跳包为 1 字节),如果在指定时间内没有收到该心跳包,则服务器会判断客户端已经断开,此时程序中的 Socket 状态机会转到 SOCKET_CLOSED 并重新打开 Socket 去连接服务器 / 监听客户端。   KeepAlive 怎么分类?          KA 根据发出方不同可以分为两种,一种是由客户端发给服务器的心跳包,一种是服务器发给客户端的心跳包,选择哪一种方式需要看哪一方实现起来方便合理。需要注意的是, W5200 根据合理的设计,其心跳包需要在 Socket TCP 连接建立之后,服务器和客户端至少进行一次数据交互,且在设定的时间内没有数据交互时发出。   W5200 KA 程序说明        下面我以 W5200 的 TCP Server 官方例程为例,用 PC 建立 TCP 客户端来连接 W5200 ,说明 KA 的实现方法。   定义和初始化部分: 程序中用到了定时器和中断函数,在 w5200_config.c 中做了定义:       void Timer_Configuration(void) {   TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);   TIM_TimeBaseStructure.TIM_Period = 1000;             TIM_TimeBaseStructure.TIM_Prescaler = 0;         TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;       TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   TIM_TimeBaseInit(TIM2, TIM_TimeBaseStructure);     TIM_PrescalerConfig(TIM2, 71, TIM_PSCReloadMode_Immediate);     TIM_Cmd(TIM2, ENABLE);   TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); void Timer2_ISR(void) {   ms++;                                                                   // 等待时间自增,单位为 ms   if((ms % 1000)==0)                                               // 当等待时间增加到某一秒   {     if(ka_tick_flag==1)ka_no_data_tick++;                  // 若 KA 定时器标志位为 1 ,无数据传输 时间计时器自增     if(ka_no_data_tick=NO_DATA_PERIOD)                  {    ka_send_tick++;                                // 当无数据传输时间计时器值大于 NO_DATA_PERIOD , KA 发送定时器开始自增     if(ka_send_tick=KA_SEND_PERIOD)       {         ka_sen       d_flag=1;                            / / 当 KA 发送定时器的大于 KA_SEND_PERIOD , KA 发送标志位置 1 ,发送一个 KA 包       }     }         printf(".");                             // 当时间没到整秒,发一个“ . ”   } }   在主程序中进行初始化: Timer_Configuration();                       // 定时器初始化 NVIC_Configuration();                        // 中断函数初始化     程序中定义了 ka_tick_flag ( KA 定时器开始计时标志位)、 ka_send_flag ( KA 发送标志位)、 ka_no_data_tick ( KA 无数据传输时间计时器)以及 ka_send_tick ( KA 发送定时器)。在 w5200_config.c 中对以上定义进行了初始化:   uint32 ka_no_data_tick=0;                                   // 定义无数据传输时间计时器 uint8 ka_tick_flag=0;                                            // 定义 KA 定时器开始计时标志位 uint32 ka_send_tick=0;                                         // 定义 KA 发送定时器 uint8 ka_send_flag=0;                                           // 定义 KA 发送标志位   主循环部分:   当程序烧录后,按 Reset 键重启 W5200 后服务器打开一个 Socket ,此时 Socket 由 SOCK_CLOSED 变为 SOCK_INIT 并处于监听状态。 PC 建立客户端成功连接 W5200 后, Socket 处于 SOCK_ESTABLISHED ,下面是程序具体的操作过程:   case SOCK_ESTABLISHED:                                                        // Socket 处于连接建立状态 if(getSn_IR(0) Sn_IR_CON)          {            setSn_IR(0, Sn_IR_CON);                                             // Sn_IR 的第 0 位置 1            ka_tick_flag=0;                                                            // KA 定时器开始计时标志位清零            ka_no_data_tick=0;                                                     // 无数据传输时间计时器            ka_send_flag=0;                                                          // KA 发送标志位清零            ka_send_tick=0;                                                          // KA 发送定时器清零          }          if ((len = getSn_RX_RSR(0)) 0)                           {                                                len = recv(0, RX_BUF, len);                                           // W5200 收到数据并保存到 len            send(0,RX_BUF,len,(bool)0);                              // W5200 将收到的数据发回客户端            if(ka_tick_flag==0)                                         {                   ka_tick_flag=1;                                               // W5200 同客户端进行了一次通信后,将 KA 定时器开始计时标志位置 1 ,进入定时器中断函数,只要接下来在 NO_DATA_PERIOD 内没有数据通信,就开始发 KA 包              }              ka_no_data_tick=0;                                                     // 无数据传输时间计时器清零              ka_send_tick=0;                                                            // KA 发送定时器清零            }          // KA 发送过程 if(ka_send_flag)          {            ka_send_flag=0;                                                             // KA 发送标志位清零            ka_send_tick=0;                                                              // KA 发送定时器清零            send_keepalive(0);                                                           // W5200 发 KA 包给客户端            printf("*");                                                                     / / KA 以 ”*” 为标志在串口打印出来          } break;   例程下载: W5200: http://pan.baidu.com/s/1eQ3vkZo W5500: http://pan.baidu.com/s/1sj7ILBn 感谢阅读!     欢迎访问: WIZnet 官方网站: http://www.iwiznet.co.kr   WIZnet 官方微博: http://weibo.com/wiznet2012 WIZnet 微信公众平台:
  • 热度 21
    2014-8-1 18:05
    1470 次阅读|
    0 个评论
    大家是否遇到过这样的问题,W5500作为服务器已经建立连接,突然网线掉了,然后再去连接W5500,就连不上了。为什么?下面对这个问题进行解释说明,并提出解决办法。 图1中的上位机程序作为客户端,连接W5500服务器。 图2是对这个问题的wireshark抓包说明。其中192.168.11.114为W5500的IP,192.168.11.110为PC的IP。下图中的第48个包是第一次握手:建立连接时,客户端发送SYN包到服务器,等待服务器确认;第49个包为第二次握手:服务器收到SYN包,必须确认客户的SYN同时自己也发送一个SYN包,即SYN+ACK包。第50个包为第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK,此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。在第70个包中显示,PC向W5500发送9个字节数据,在第73个包中,W5500向PC发送9个字节数据。此时,突然拔掉网线,并点击图1 “Disconnect”按钮,图1中的第160个包显示的是PC发送FIN+ACK包,第161包,W5500发送应答。然后连上网线,并且点击图3的“connect”,但是无法连接。 这是因为,网线没掉之前,W5500处于SOCK_ESTABLISHED状态,此时突然拔掉网线,SOCKET状态没变,还是SOCK_ESTABLISHED状态,没有监听,所以无法再次连接。 图1 wireshark抓包 图2 上位机建立连接 图3 网线掉了,再插上网线连接不上 解决方法: Sn_KPALVTR寄存器配置了socket  n 的keep-alive包传输时间间隔。只在TCP模式下生效,单位时间为5秒。Keep-alive包会在Sn-SR 寄存器变为SOCK_ESTABLISHED之后,且与对方至少进行过一次收或发的通信后进行传输。如果Sn_KPALVTR0,W5500在设置的时间间隔后自动传输keep-alive包以检查TCP的连接状态(自动在线检验),如果对方不能在超时计数期内反馈keep-alive包,这个连接将会被关闭并触发超时中断。如果‘Sn_KPALVTR = 0’,将不会启动自动在线验证,主机可以通过向寄存器Sn-CR写入SEND_KEEP命令发送keep-alive包(手动在线验证)。在‘Sn_KPALVTR 0’时,将会无视手动在线验证。 自动检验:只需在主函数中,向寄存器Sn_KPALVTR写入不为0的数,即可启动自动在线检验。在函数中写入下面的函数,那么在W5500与对方进行过一次数据通信后,10秒后W5500自动发送keep-alive包。 例如:voidsetkeepalive(SOCKET s) { IINCHIP_WRITE(Sn_KPALVTR(s),0x02); } Wireshark抓包如图4 1-3包是三次握手过程,5-10包是发送和接收数据的过程,19包是W5500向PC发送keep-alive包,20包是PC对keep-alive包的应答。10秒之后,即是第30包,W5500又发送一次keep-alive包。此时拔掉网线,点击“Disconnect”。10秒之后,W5500发送的keep-alive包没有反应,SOCKET关闭。然后连上网线,点击“Connect”按钮,可以重新建立连接,109-111包是第二次建立连接过程。 图4 启用keep-alive后可以重新建立连接 以上演示的是自动发送keep-alive包的过程,如果想手动发送keep-alive包,把Sn_KPALVTR寄存器写入0,当向Sn-CR写入SEND_KEEP命令时,W5500发送一次keep-alive包。 voidsend_ka(SOCKET s) { IINCHIP_WRITE(Sn_CR(s),Sn_CR_SEND_KEEP); return; }  By Catherine 程序下载: W5500 TCP Server自动发送keep-alive.rar 如有任何问题,请联系:wiznetbj@wiznet.co.kr
  • 热度 21
    2014-8-1 18:04
    2186 次阅读|
    0 个评论
    大家是否遇到过这样的问题,W5500作为服务器已经建立连接,突然网线掉了,然后再去连接W5500,就连不上了。为什么?下面对这个问题进行解释说明,并提出解决办法。 图1中的上位机程序作为客户端,连接W5500服务器。 图2是对这个问题的wireshark抓包说明。其中192.168.11.114为W5500的IP,192.168.11.110为PC的IP。下图中的第48个包是第一次握手:建立连接时,客户端发送SYN包到服务器,等待服务器确认;第49个包为第二次握手:服务器收到SYN包,必须确认客户的SYN同时自己也发送一个SYN包,即SYN+ACK包。第50个包为第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK,此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。在第70个包中显示,PC向W5500发送9个字节数据,在第73个包中,W5500向PC发送9个字节数据。此时,突然拔掉网线,并点击图1 “Disconnect”按钮,图1中的第160个包显示的是PC发送FIN+ACK包,第161包,W5500发送应答。然后连上网线,并且点击图3的“connect”,但是无法连接。 这是因为,网线没掉之前,W5500处于SOCK_ESTABLISHED状态,此时突然拔掉网线,SOCKET状态没变,还是SOCK_ESTABLISHED状态,没有监听,所以无法再次连接。 图1 wireshark抓包 图2 上位机建立连接 图3 网线掉了,再插上网线连接不上 解决方法: Sn_KPALVTR寄存器配置了socket  n 的keep-alive包传输时间间隔。只在TCP模式下生效,单位时间为5秒。Keep-alive包会在Sn-SR 寄存器变为SOCK_ESTABLISHED之后,且与对方至少进行过一次收或发的通信后进行传输。如果Sn_KPALVTR0,W5500在设置的时间间隔后自动传输keep-alive包以检查TCP的连接状态(自动在线检验),如果对方不能在超时计数期内反馈keep-alive包,这个连接将会被关闭并触发超时中断。如果‘Sn_KPALVTR = 0’,将不会启动自动在线验证,主机可以通过向寄存器Sn-CR写入SEND_KEEP命令发送keep-alive包(手动在线验证)。在‘Sn_KPALVTR 0’时,将会无视手动在线验证。 自动检验:只需在主函数中,向寄存器Sn_KPALVTR写入不为0的数,即可启动自动在线检验。在函数中写入下面的函数,那么在W5500与对方进行过一次数据通信后,10秒后W5500自动发送keep-alive包。 例如:voidsetkeepalive(SOCKET s) { IINCHIP_WRITE(Sn_KPALVTR(s),0x02); } Wireshark抓包如图4 1-3包是三次握手过程,5-10包是发送和接收数据的过程,19包是W5500向PC发送keep-alive包,20包是PC对keep-alive包的应答。10秒之后,即是第30包,W5500又发送一次keep-alive包。此时拔掉网线,点击“Disconnect”。10秒之后,W5500发送的keep-alive包没有反应,SOCKET关闭。然后连上网线,点击“Connect”按钮,可以重新建立连接,109-111包是第二次建立连接过程。 图4 启用keep-alive后可以重新建立连接 以上演示的是自动发送keep-alive包的过程,如果想手动发送keep-alive包,把Sn_KPALVTR寄存器写入0,当向Sn-CR写入SEND_KEEP命令时,W5500发送一次keep-alive包。 voidsend_ka(SOCKET s) { IINCHIP_WRITE(Sn_CR(s),Sn_CR_SEND_KEEP); return; }  By Catherine 程序下载: W5500 TCP Server自动发送keep-alive.rar 如有任何问题,请联系:wiznetbj@wiznet.co.kr