HTTP的“長連接"初探

背景
項目的一個功能:持續異步通知下游服務器消息,獲取下游服務器的消息返回並處理。

思路

(1)開啓一個timer.schece線程啓動定時任務;
(2)服務與下游的url(Controller)建立一個Http連接,並response.writer消息;
(3)2min鍾後,收到下游的消息或者沒有收到,再response.outputStream消息,發現此時行不通。服務端會報空Host錯誤。

問題分析

之所以產生這個解決思路,是因爲看到HTTP可以設置“keep-alive”而建立長連接(其實這個keep-alive是指TCP的連接)。這裏樓主踩坑了

  • 以下是分析錯誤的過程:
    HTTP協議是建立在TCP協議之上的一種應用。HTTP連接最顯著的特點是客戶端發送的每次請求都需要服務器回送響應,在請求結束後,會主動釋放連接。從建立連接到關閉連接的過程稱爲“一次連接”。 Http服務所有的響應都是在有請求的情況下才能Response,即Http是一次請求、響應、關閉服務。並不是建立連接、發送消息、關閉連接這種模式。
    而在請求中加上“keep-alive”的意思並不是保持HTTP長連接,而是保持其傳輸層的TCP長連接,避免客戶端再一次發請求建立TCP連接,建立TCP連接需要3次握手協議等,網絡開銷比較大。
    所以在上面第3步中,不能直接response.outputStream繼續發消息,而是應該new URL(url)從新訪問下游的url。我們的服務扮演的是客戶端。

拓展,怎樣“真正”長連接?

需要用到Socket套接字技術。

套接字(socket)是通信的基石,是支持TCP/IP協議的網絡通信的基本操作單元。它是網絡通信過程中端點的抽象表示,包含進行網絡通信必須的五種信息:連接使用的協議,本地主機的IP地址,本地進程的協議端口,遠地主機的IP地址,遠地進程的協議端口。
應用層通過傳輸層進行數據通信時,TCP會遇到同時爲多個應用程序進程提供併發服務的問題。多個TCP連接或多個應用程序進程可能需要通過同一個 TCP協議端口傳輸數據。爲了區別不同的應用程序進程和連接,許多計算機操作系統爲應用程序與TCP/IP協議交互提供了套接字(Socket)接口。應 用層可以和傳輸層通過Socket接口,區分來自不同應用程序進程或網絡連接的通信,實現數據傳輸的併發服務。
套接字之間的連接過程分爲三個步驟:服務器監聽,客戶端請求,連接確認。

服務器監聽:服務器端套接字並不定位具體的客戶端套接字,而是處於等待連接的狀態,實時監控網絡狀態,等待客戶端的連接請求。
客戶端請求:指客戶端的套接字提出連接請求,要連接的目標是服務器端的套接字。爲此,客戶端的套接字必須首先描述它要連接的服務器的套接字,指出服務器端套接字的地址和端口號,然後就向服務器端套接字提出連接請求。
連接確認:當服務器端套接字監聽到或者說接收到客戶端套接字的連接請求時,就響應客戶端套接字的請求,建立一個新的線程,把服務器端套接字的描述發給客戶 端,一旦客戶端確認了此描述,雙方就正式建立連接。而服務器端套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連接請求。


Socket連接與Http連接的區別

由於通常情況下Socket連接就是TCP連接,因此Socket連接一旦建立,通信雙方即可開始相互發送數據內容,直到雙方連接斷開。但在實際網絡應用 中,客戶端到服務器之間的通信往往需要穿越多箇中間節點,例如路由器、網關、防火牆等,大部分防火牆默認會關閉長時間處於非活躍狀態的連接而導致 Socket 連接斷連,因此需要通過輪詢告訴網絡,該連接處於活躍狀態。

而HTTP連接使用的是“請求—響應”的方式,不僅在請求時需要先建立連接,而且需要客戶端向服務器發出請求後,服務器端才能回覆數據。

很多情況下,需要服務器端主動向客戶端推送數據,保持客戶端與服務器數據的實時與同步。
此時若雙方建立的是Socket連接,服務器就可以直接將數據傳送 給客戶端;
若雙方建立的是HTTP連接,則服務器需要等到客戶端發送一次請求後才能將數據傳回給客戶端,因此,客戶端定時向服務器端發送連接請求,不僅可 以保持在線,同時也是在“詢問”服務器是否有新的數據,如果有就將數據傳給客戶端。

發佈了29 篇原創文章 · 獲贊 24 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章