怎樣解決W5200/W5500在TCP通訊過程中意外斷開?(Keepalive)
在使用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微信公眾平臺:
相關文章
- TCP/IP的通訊過程-VeCloudTCPCloud
- 儲存意外斷電導致raid資訊丟失的解決過程AI
- 在開發過程中怎樣利用單元和功能測試
- TCP通訊之經典問題解決TCP
- 怎樣在 Ubuntu 和 Debian 中通過命令列管理 KVMUbuntu命令列
- 移遠 EC20 模組(4G通訊模組)AT指令測試 TCP 通訊過程TCP
- Qt TCP通訊客戶端斷開連線有哪些方法QTTCP客戶端
- Linux中的TCP通訊LinuxTCP
- 最新最全的Portlet 通訊過程詳解
- TCP通訊TCP
- RAC 在安裝時意外中斷, root.sh指令碼一閃而過指令碼
- [轉載]TCP keepalive的詳解(解惑)TCP
- 圖解Flutter建立Isolate的過程及通訊圖解Flutter
- 【故障診斷】cr塊slot notfound解決過程
- enq: HW - contention診斷及解決過程ENQ
- https的通訊過程HTTP
- Flink - 元件通訊過程元件
- 在 Python 除錯過程中設定不中斷的斷點Python除錯斷點
- modbus tcp通訊TCP
- iphone通話小解決方法 iphone通話聲音小怎樣解決?iPhone
- TCP通訊處理粘包詳解TCP
- Nucleus中斷處理過程!!!!
- 漫遊ZooKeeper nio通訊過程
- 一次HTTP通訊過程HTTP
- 使用tcpdump觀察DNS通訊過程TCPDNS
- 怎樣在敏捷開發中做到“事半功倍”敏捷
- 在短視訊時代怎樣通過“優獲客”的方式進行網路營銷
- 在pytorch框架下,訓練model過程中,loss=nan問題時該怎麼解決?PyTorch框架NaN
- 清晰易懂TCP通訊原理解析(附demo、簡易TCP通訊庫原始碼、解決沾包問題等)C#版TCP原始碼C#
- 例項詳解不同VLAN間通訊(轉發過程)
- 網路通訊2:TCP通訊實現TCP
- 網路通訊3:TCP互動通訊TCP
- 網路通訊2:TCP簡單通訊TCP
- 解決電子書包中即時通訊的對話記錄樣式
- PostgreSQL DBA(187) - TCP keepaliveSQLTCP
- puppeteer在開發過程中的實踐
- munium學習過程中問題解決
- PHP-FPM 與 NGINX 通訊過程PHPNginx