日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LWIP应用开发|心跳机制

發布時間:2023/12/14 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LWIP应用开发|心跳机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

心跳機制

1. 心跳機制簡介

在長連接下,可能很長一段時間都沒有數據往來。理論上說,這個連接是一直保持連接的,但是實際情況中,如果中間節點出現什么故障是難以知道的。更致命的是,有的節點(防火墻)會自動把一定時間之內沒有數據交互的連接給斷掉。這個時候,就可以使用心跳包,來維持長連接以及?;?/p>

心跳機制就是每隔幾分鐘發送一個固定信息給服務端,服務端收到后回復一個固定信息如果服務端幾分鐘內沒有收到客戶端信息則視客戶端斷開。發包方可以是客戶也可以是服務端,具體看哪邊實現更方便合理

心跳包的發送通常有以下兩種技術

  • 應用層自已實現的心跳包:
    由應用程序自己發送心跳包來檢測連接是否正常,服務器每隔一定時間向客戶端發送一個短小的數據包,然后啟動一個線程,在線程中不斷檢測客戶端的回應, 如果在一定時間內沒有收到客戶端的回應,即認為客戶端已經掉線;同樣,如果客戶端在一定時間內沒有收到服務器的心跳包,則認為連接不可用
  • 使用SO_KEEPALIVE套接字選項:
    在TCP的機制里面,本身是存在有心跳包的機制的,也就是TCP的選項. 不論是服務端還是客戶端,一方開啟KeepAlive功能后,就會自動在規定時間內向對方發送心跳包, 而另一方在收到心跳包后就會自動回復,以告訴對方我仍然在線

下面將介紹如何使用SO_KEEPALIVE套接字選項來實現心跳檢測

2. 心跳檢測實現

2.1 setsockopt函數介紹

函數功能:設置與某個套接字關聯的選項。選項可能存在于多層協議中,它們總會出現在最上面的套接字層。當操作套接字選項時,選項位于的層和選項的名稱必須給出。為了操作套接字層的選項,應該將層的值指定為SOL_SOCKET。為了操作其它層的選項,控制選項的合適協議號必須給出。例如,為了表示一個選項由TCP協議解析,層應該設定為協議號TCP

函數原型:int setsockopt(int sock, //將要被設置選項的套接字int level, //選項所在的協議層int optname, //需要訪問的選項名const void *optval, //指向包含新選項值得緩沖socklen_t optlen) //現選項的長度 返 回 值:成功返回0;失敗返回-1

參數(level)詳細說明:level是指定控制套接字的層次,可以取如下三種值

  • SOL_SOCKET:通用套接字選項
選項名稱(optname)   說明          數據類型 ======================================================================== SO_BROADCAST      允許發送廣播數據         int SO_DEBUG        允許調試            int SO_DONTROUTE      不查找             int SO_ERROR        獲得套接字錯誤         int SO_KEEPALIVE      保持連接            int SO_LINGER        延遲關閉連接          struct linger SO_OOBINLINE      帶外數據放入正常數據流     int SO_RCVBUF        接收緩沖區大小         int SO_SNDBUF        發送緩沖區大小         int SO_RCVLOWAT       接收緩沖區下限         int SO_SNDLOWAT       發送緩沖區下限         int SO_RCVTIMEO       接收超時            struct timeval SO_SNDTIMEO       發送超時            struct timeval SO_REUSERADDR      允許重用本地地址和端口     int SO_TYPE         獲得套接字類型         int SO_BSDCOMPAT      與BSD系統兼容          int ========================================================================
  • IPPROTO_IP:IP選項
選項名稱(optname)   說明          數據類型 ======================================================================== IP_HDRINCL       在數據包中包含IP首部      int IP_OPTINOS       IP首部選項           int IP_TOS         類型 IP_TTL         生存時間             int ========================================================================
  • IPPROTO_TCP:TCP選項
選項名稱(optname)   說明          數據類型 ======================================================================== TCP_MAXSEG      TCP最大數據段的大小        int TCP_NODELAY      不使用Nagle算法          int ========================================================================
2.2 心跳機制的實現

該實例實現的功能:在TCP客戶端代碼中加入心跳機制,使服務端在斷網重連(與客戶端)后,能自動保持連接

  • 參考Socket API編程優化一文,在該文的工程源碼基礎上進行修改
  • keepalive宏開關:將opt.h文件中的LWIP_TCP_KEEPALIVE宏定義開啟
/*** LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT* options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set* in seconds. (does not require sockets.c, and will affect tcp.c)*/ #if !defined LWIP_TCP_KEEPALIVE || defined __DOXYGEN__ #define LWIP_TCP_KEEPALIVE 1 #endif
  • setsockopt參數含義:sockets.h文件中可以看到如下setsockopt參數的設置
#define SO_KEEPALIVE 0x0008 /* 保持連接 */ #define TCP_KEEPIDLE 0x03 /* 發送心跳空閑周期 S*/ #define TCP_KEEPINTVL 0x04 /* 發送心跳間隔 S */ #define TCP_KEEPCNT 0x05 /* 心跳重發次數 */
  • 在工程中創建tcp_keepalive.c和對應的頭文件
#include "socket_tcp_server.h" #include "tcp_keepalive.h" #include "socket_wrap.h" #include "ctype.h" #include "FreeRTOS.h" #include "task.h" static char ReadBuff[BUFF_SIZE]; void vTcpKeepaliveTask(void){int cfd, n, i, ret;struct sockaddr_in server_addr;int so_keepalive_val = 1;int tcp_keepalive_idle = 3;int tcp_keepalive_intvl = 3;int tcp_keepalive_cnt = 3;int tcp_nodelay = 1; again: //創建socketcfd = Socket(AF_INET, SOCK_STREAM, 0);//使能socket層的心跳檢測setsockopt(cfd, SOL_SOCKET, SO_KEEPALIVE, &so_keepalive_val, sizeof(int));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(SERVER_PORT);server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);/*連接到服務器(connect是一個阻塞接口,內部要完成TCP的三次握手;里面有超時機制,所以需要等一段時間,才能重新連接到服務器)*/ret = Connect(cfd, (struct sockaddr*)&server_addr, sizeof(server_addr));if(ret < 0){//100ms去連接一次服務器vTaskDelay(100);goto again;}//配置心跳檢測參數 默認參數時間很長setsockopt(cfd, IPPROTO_TCP, TCP_KEEPIDLE, &tcp_keepalive_idle, sizeof(int)); setsockopt(cfd, IPPROTO_TCP, TCP_KEEPINTVL, &tcp_keepalive_intvl, sizeof(int)); setsockopt(cfd, IPPROTO_TCP, TCP_KEEPCNT, &tcp_keepalive_cnt, sizeof(int)); setsockopt(cfd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay, sizeof(int)); printf("server is connect ok\r\n");while(1){//等待服務器發送數據n = Read(cfd, ReadBuff, BUFF_SIZE);if(n <= 0){ goto again; }//進行大小寫轉換for(i = 0; i < n; i++){ ReadBuff[i] = toupper(ReadBuff[i]); }//寫回服務器n = Write(cfd, ReadBuff, n);if(n <= 0){ goto again; } } }
  • 在freertos.c文件中的默認任務里面添加代碼
void StartDefaultTask(void const * argument){/* init code for LWIP */MX_LWIP_Init();/* USER CODE BEGIN StartDefaultTask */printf("TCP keepalive test!\r\n");/* Infinite loop */for(;;){vTcpKeepaliveTask();osDelay(100);}/* USER CODE END StartDefaultTask */ }
2.3 心跳機制的測試比較

未加入心跳機制的代碼測試

參考Socket API編程優化,將未加入心跳機制的TCP客戶端代碼下載到開發板中,開發板與電腦用網線連接好,設置到對應的IP地址信息(192.168.1.20)

  • 開啟網絡調試助手,打開一個服務端,監聽192.168.1.20/端口6666;串口輸出調試信息(server is connect ok);在服務器端輸入小寫字母,客戶端會返回對應的大寫字母


  • 將電腦和開發板之間的網線拔掉后重新連接,串口沒有輸出任何信息,仍顯示server is connect ok;在服務器端發送信息,此時提示未建立通訊


加入心跳機制的代碼測試

將2.2章節的心跳檢測實例下載到開發板中,用網線連接電腦和開發板,確保串口通訊和服務器監聽正常

  • 電腦和開發板之間的網線拔掉后,串口會輸出錯誤信息“read socket error”,重新連接網線后,串口輸出“server is connect ok”,表示已自動重新建立連接;網線重連后,在服務器端發送信息,能夠正?;仫@對應的大寫字母,表示服務端和客戶端的通訊正常


總結

以上是生活随笔為你收集整理的LWIP应用开发|心跳机制的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。