1. 程式人生 > >TCP(HTTP)長連線和短連線區別和怎樣維護長連線

TCP(HTTP)長連線和短連線區別和怎樣維護長連線

一、HTTP協議和TCP協議

HTTP的長連線和短連線本質上是TCP長連線和短連線。HTTP屬於應用層協議,在傳輸層使用TCP協議,在網路層使用IP協議。IP協議主要解決網路路由和定址問題,TCP協議主要解決如何在IP層之上可靠的傳遞資料包,使在網路上的另一端收到發端發出的所有包,並且順序與發出順序一致。TCP有可靠,面向連線的特點。

二、HTTP協議的長連線和短連線

在HTTP/1.0中,預設使用的是短連線。也就是說,瀏覽器和伺服器每進行一次HTTP操作,就建立一次連線,但任務結束就中斷連線。如果客戶端瀏覽器訪問的某個HTML或其他型別的 Web頁中包含有其他的Web資源,如JavaScript檔案、影象檔案、CSS檔案等;當瀏覽器每遇到這樣一個Web資源,就會建立一個HTTP會話

但從 HTTP/1.1起,預設使用長連線,用以保持連線特性。使用長連線的HTTP協議,會在響應頭有加入這行程式碼:

Connection:keep-alive

在使用長連線的情況下,當一個網頁開啟完成後,客戶端和伺服器之間用於傳輸HTTP資料的 TCP連線不會關閉,如果客戶端再次訪問這個伺服器上的網頁,會繼續使用這一條已經建立的連線。Keep-Alive不會永久保持連線,它有一個保持時間,可以在不同的伺服器軟體(如Apache)中設定這個時間。實現長連線要客戶端和服務端都支援長連線。

HTTP協議的長連線和短連線,實質上是TCP協議的長連線和短連線。

三、TCP長連線和短連線:

我們模擬一下TCP短連線的情況,client向server發起連線請求,server接到請求,然後雙方建立連線。client向server 傳送訊息,server迴應client,然後一次讀寫就完成了,這時候雙方任何一個都可以發起close操作,不過一般都是client先發起 close操作。為什麼呢,一般的server不會回覆完client後立即關閉連線的,當然不排除有特殊的情況。從上面的描述看,短連線一般只會在 client/server間傳遞一次讀寫操作

短連線的優點是:管理起來比較簡單,存在的連線都是有用的連線,不需要額外的控制手段

接下來我們再模擬一下長連線的情況,client向server發起連線,server接受client連線,雙方建立連線。Client與server完成一次讀寫之後,它們之間的連線並不會主動關閉,後續的讀寫操作會繼續使用這個連線。

首先說一下TCP/IP詳解上講到的TCP保活功能,保活功能主要為伺服器應用提供,伺服器應用希望知道客戶主機是否崩潰,從而可以代表客戶使用資源。如果客戶已經消失,使得伺服器上保留一個半開放的連線,而伺服器又在等待來自客戶端的資料,則伺服器將應遠等待客戶端的資料,保活功能就是試圖在服務 器端檢測到這種半開放的連線。

四、長連線和短連線的生命週期

短連線在建立連線後,完成一次讀寫就會自動關閉了。

正常情況下,一條TCP長連線建立後,只要雙不提出關閉請求並且不出現異常情況,這條連線是一直存在的,作業系統不會自動去關閉它,甚至經過物理網路拓撲的改變之後仍然可以使用。所以一條連線保持幾天、幾個月、幾年或者更長時間都有可能,只要不出現異常情況或由使用者(應用層)主動關閉。

在程式設計中,往往需要建立一條TCP連線,並且長時間處於連線狀態。所謂的TCP長連線並沒有確切的時間限制,而是說這條連線需要的時間比較長。

五、怎樣維護長連線或者檢測中斷

1、在應用層使用heartbeat來主動檢測。

對於實時性要求較高的網路通訊程式,往往需要更加及時的獲取已經中斷的連線,從而進行及時的處理。但如果對方的連線異常中斷,往往是不能及時的得到對方連線已經中斷的資訊,作業系統檢測連線是否中斷的時間間隔預設是比較長的,即便它能夠檢測到,但卻不符合我們的實時性需求,所以需要我們進行手工去不斷探測。

探測的方式有兩種:

2、改變socket的keepalive選項,以使socket檢測連線是否中斷的時間間隔更小,以滿足我們的及時性需求。有關的幾個選項使用和解析如下:

A、我們在檢測對端以一種非優雅的方式斷開連線的時候,可以設定SO_KEEPALIVE屬性使得我們在2小時以後發現對方的TCP連線是否依然存在。用法如下:

keepAlive = 1

setsockopt(listenfd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive));

B、如果我們不想使用這麼長的等待時間,可以修改核心關於網路方面的配置引數,也可設定SOCKETTCP層(SOL_TCP)選項TCP_KEEPIDLETCP_KEEPINTVLTCP_KEEPCNT

TCP_KEEPIDLE:開始首次KeepAlive探測前的TCP空閉時間

The tcp_keepidle parameter specifies the interval of inactivity that causes TCP to generate a KEEPALIVE transmission for an application that requests them. tcp_keepidle defaults to 14400 (two hours).

TCP_KEEPINTVL:兩次KeepAlive探測間的時間間隔

The tcp_keepintvl parameter specifies the interval between the nine retries that are attempted if a KEEPALIVE transmission is not acknowledged. tcp_keepintvl defaults to 150 (75 seconds).

TCP_KEEPCNT:斷開前的KeepAlive探測次數

The TCP_KEEPCNT option specifies the maximum number of keepalive probes to be sent. The value of TCP_KEEPCNT is an integer value between 1 and n, where n is the value of the systemwide tcp_keepcnt parameter. 

如果心搏函式要維護客戶端的存活,即伺服器必須每隔一段時間必須向客戶段傳送一定的資料,那麼使用SO_KEEPALIVE是有很大的不足的。因為SO_KEEPALIVE選項指"此套介面的任一方向都沒有資料交換"。在Linux 2.6系列上,上面話的理解是隻要開啟SO_KEEPALIVE選項的套介面端檢測到資料傳送或者資料接受就認為是資料交換。因此在這種情況下使用 SO_KEEPALIVE選項 檢測對方是否非正常連線是完全沒有作用的,在每隔一段時間發包的情況, keep-alive的包是不可能被髮送的。上層程式在非正常斷開的情況下是可以正常傳送包到緩衝區的。非正常端開的情況是指伺服器沒有收到"FIN" 或者 "RST"包。