TCP長連接詳解

一、什麼是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-hk/n/198658.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-04 10:26
下一篇 2024-12-04 10:26

相關推薦

  • NodeJS 建立TCP連接出現粘包問題

    在TCP/IP協議中,由於TCP是面向位元組流的協議,發送方把需要傳輸的數據流按照MSS(Maximum Segment Size,最大報文段長度)來分割成若干個TCP分節,在接收端…

    編程 2025-04-29
  • TCP發送的數據包發佈全

    TCP協議是一種可靠的面向連接的協議,而數據包的發送則是其重要組成部分,本文將從多個方面對TCP發送的數據包發佈全進行詳細闡述。 一、數據包的概念 數據包指的是網絡傳輸過程中,為了…

    編程 2025-04-27
  • 神經網絡代碼詳解

    神經網絡作為一種人工智能技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網絡的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網絡模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁盤中。在執行sync之前,所有的文件系統更新將不會立即寫入磁盤,而是先緩存在內存…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性傳感器,能夠同時測量加速度和角速度。它由三個傳感器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分佈式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變量讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25

發表回復

登錄後才能評論