一、什麼是TCP長連接
TCP連接在網絡通信中絕對是一個基礎、關鍵而又常見的概念。而長連接又是TCP連接的一種特殊形態。所謂TCP長連接,指的是建立起來的TCP連接不會輕易的中斷或關閉,而是一直保持連接狀態,直至完成或出現意外斷連。
與之對應的是短連接,即數據傳輸一次完成後,連接就會自動關閉。相比之下,長連接有很多優點,因此在實際開發中非常常用。我們可以通過幾種方式來實現TCP長連接:保持TCP連接處於連接狀態、服務器空閑狀態發送心跳包來實現保活機制、應用層心跳等,後面我們會詳細介紹這些內容。
二、TCP長連接的優點和缺點
長連接的優點主要有以下幾點:
1、減少了TCP的握手次數,減少了資源的佔用。
2、避免了服務端資源的頻繁分配,提高了性能。
3、客戶端可以更快速的獲取到服務器上的數據,同時也提高了用戶的體驗。
然而,長連接也存在缺點:
1、可能存在部分數據丟失。長連接在通信過程中,因為網絡的原因,一些數據可能會丟失,但不會造成太大的影響。
2、連接長久不關閉會對服務器端的性能造成威脅。因為長連接需要服務器端佔用一定的資源保持狀態,如果長時間不關閉就會對服務器造成一定的負擔。
三、保持TCP連接處於連接狀態
我們可以通過設置TCP的keep-alive屬性讓TCP連接一直處於連接狀態。keep-alive會定時地給服務器發一個TCP包以判斷連接是否終止,從而保持連接不斷開。
// C語言實現,設置TCP_KEEPALIVE屬性 int keepalive = 1; //開啟KEEPALIVE屬性 int keepidle = 60; //如果60秒內沒有任何數據交互,TCP會發送檢驗包(稱為保持存活探測分節)。 int keepinterval = 5; //檢驗包的發送間隔默認為75秒收不到保持存活探測分節後,才會發送第一個探測分節 int keepcount = 3; //如果第1次檢測包發送失敗,則每隔5秒發送第二個檢測包,最多發送3個檢測包。如果3次都沒成功,就當連接失效斷掉。 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive, sizeof(keepalive)); //開啟keepalive功能 setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (void*)&keepidle, sizeof(keepidle)); //設置當有數據報要發送時Kernel會等待多長時間,才會發這個數據報。單位為秒。 setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepinterval, sizeof(keepinterval)); //設置每次發送數據報的時間間隔,默認為75秒。 setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, (void *)&keepcount, sizeof(keepcount)); //設置發送保持存活探測分節的次數。默認是9次。
四、服務器空閑狀態發送心跳包實現保活機制
除了設置TCP的keep-alive屬性之外,還可以採用心跳機制來保持TCP長連接。服務器不斷地向客戶端發送心跳包來判斷連接的狀態,從而實現保活機制。實現起來比設置TCP的keep-alive屬性要容易一些。
//C語言實現 int SendData(int fd, char *buffer, int len, int flags) { int nsend = 0; nsend = send(fd, buffer, len, flags); if (nsend == -1) { //send 發送失敗 if(errno == EINTR) /*信號中斷*/ { //稍後重發 } else if(errno == EAGAIN || errno == EWOULDBLOCK) /*一般錯誤類型*/ { //稍後重發 } else /*其他錯誤類型,關閉fd*/ { //CLOSED端口fd } } return nsend; } int recv_with_timeout(int fd, char *buf, int data_size, int timeout) { fd_set fds; struct timeval tv; int ret = 0; FD_ZERO(&fds); FD_SET(fd, &fds); tv.tv_sec = timeout; tv.tv_usec = 0; ret = select(fd+1, &fds, NULL, NULL, &tv); switch(ret) { case -1: /* error occurred */ perror("select error:"); return -1; case 0: /* timed out */ return -2; default: /* data ready */ if (FD_ISSET(fd, &fds)) return recv(fd, buf, data_size, 0); } return -3; } char buffer[1024]; while(true) { SendData(fd, "HeartBeat", sizeof("HeartBeat"), 0); //服務器定時發送心跳包 int res = recv_with_timeout(fd, buffer, 4, 5); //設置5秒的等待時間 if(res == -2) { //客戶端長時間未響應,服務端可以關閉連接 } }
五、應用層心跳
應用層心跳,就是通過應用程序在長連接上發送一定類型的消息,以達到保持連接狀態的目的。在實際中,應用層心跳的靈活性和可控性都較高,但也需要我們自己來設計和實現心跳包的規則。
//C語言實現 while(true) { SendData(fd, "HeartBeat", sizeof("HeartBeat"), 0); //發送應用層心跳包 sleep(5); //定時發送心跳 }
六、結束語
以上就是關於TCP長連接的詳細講解,包括了長連接的定義、優缺點、保持TCP連接處於連接狀態、服務器空閑狀態發送心跳包實現保活機制、以及應用層心跳等多個方面。我們可以結合實際項目和需求來選擇不同的實現方式,以達到最佳的效果。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/198658.html