HTTP長連接和短連接 + Websocket


HTTP協議與TCP/IP協議的關系

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

長連接短連接操作過程

短連接的操作步驟是:

建立連接——數據傳輸——關閉連接…建立連接——數據傳輸——關閉連接

長連接的操作步驟是:

建立連接——數據傳輸 …(保持連接)… 數據傳輸——關閉連接

長連接和短連接的優點和缺點

長連接可以省去較多的TCP建立和關閉的操作,減少浪費,節約時間。但是如果連接數比較多,會給服務器造成比較大壓力。

短連接對於服務器來說管理較為簡單,存在的連接都是有用的連接,不需要額外的控制手段。但如果客戶請求頻繁,將在TCP的建立和關閉操作上浪費時間和帶寬。

什么時候用長連接,短連接

長連接多用於操作頻繁,點對點的通訊,而且連接數不能太多情況。例如:數據庫的連接用長連接, 如果用短連接頻繁的通信會造成socket錯誤,而且頻繁的socket 創建也是對資源的浪費。

而像WEB網站的http服務一般都用短鏈接,因為長連接對於服務端來說會耗費一定的資源,而像WEB網站這么頻繁的成千上萬甚至上億客戶端的連接用短連接會更省一些資源,如果用長連接,而且同時有成千上萬的用戶,如果每個用戶都占用一個連接的話,那可想而知吧。所以並發量大,但每個用戶無需頻繁操作情況下需用短連好。

推送服務

推送技術,又名反向AJAX,指的是一種基於Internet,將由中心或發布者發出消息傳輸給用戶的技術。與之相對的是拉取(參見AJAX),這種情況下請求是由用戶或客戶端主動發起的。

所有的推送功能都是基於長連接的基礎上的。

維護任何一個長連接都需要心跳機制,客戶端發送一個心跳給服務器,服務器給客戶端一個心跳應答,這樣就形成客戶端服務器的一次完整的握手,這個握手是讓雙方都知道他們之間的連接是沒有斷開,客戶端是在線的。如果超過一個時間的閾值,客戶端沒有收到服務器的應答,或者服務器沒有收到客戶端的心跳,那么對客戶端來說則斷開與服務器的連接重新建立一個連接,對服務器來說只要斷開這個連接即可。

在智能手機上的長連接心跳和在Internet上的長連接心跳有什么不同的目的呢?原因就在於智能手機使用的是移動無線網絡,那么我們在講長連接之前我們首先要了解無線移動網絡的特點。

簡單來說就是由於網絡運營商為了節省信道資源,會在一台移動終端一段時間沒有通信時關閉其關的鏈路。為了應對這種情況,移動應用不得不以遠高於正常頻率來發送心跳用以維護推送的長連接。

Android系統的推送和iOS的推送

ios長連接是由系統來維護的,iOS上的所有應用上的推送都是先將消息推送到蘋果的服務器然后將蘋果服務器通過這個系統級別的長鏈接推送到手機終端上,這樣做的好處是:

  1. 在手機終端始終只要維護一個長連接即可,而且由於這個長鏈接是系統級別的不會出現被殺死而無法推送的情況。
  2. 省電,不會出現每個應用都各自維護一個自己的長連接。
  3. 安全,只有在蘋果注冊的開發者才能夠進行推送,等等。

Android的長連接是由每個應用各自維護的,而谷歌退出的和蘋果類似的推送框架在國內無法使用的。

推送的常見方式

  1. 輪詢(polling)
  2. 持久鏈接(binding)
  3. SMS方式

WebSocket

WebSocket API是下一代客戶端-服務器的異步通信方法。該通信取代了單個的TCP套接字,使用ws或wss協議,可用於任意的客戶端和服務器程序。

WebSocket API最偉大之處在於服務器和客戶端可以在給定的時間范圍內的任意時刻,相互推送信息。WebSocket並不限於以Ajax(或XHR)方式通信,因為Ajax技術需要客戶端發起請求,而WebSocket服務器和客戶端可以彼此相互推送信息;XHR受到域的限制,而WebSocket允許跨域通信。

WebSocket的客戶端API

// 創建一個Socket實例,ws表示WebSocket協議 var socket = new WebSocket('ws://localhost:8080'); // 打開socket socket.onopen = function(event){ // 發送一個初始化消息 socket.send('hello socket') // 監聽消息 socket.onmessage = function(event){ console.log('client reveived a meessage', event) } // 監聽Socket的關閉 socket.oncolse = function(event){ console.log('Client notified socket has closed', event) } // 關閉Socket socket.closd() }

一個模擬聊天室websocket的例子:

在實際應用中,socket服務器端的代碼可以是Python,node.js,java,php。在這里使用http://www.websocket.org/網站提供的,socket 
服務端。協議地址為:ws://echo.websocket.org/

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Websocket</title> <style> * { margin: 0; padding: 0; } #outer { box-sizing: border-box; width: 60%; height: 400px; padding: 20px 200px; background: black; font-size: 20px; color: #F8F8F8; overflow-y: auto; } #message { width: 300px; height: 20px; margin-top: 10px; margin-left: 100px; margin-right: 50px; } p { margin: 10px 0; } button { background: none; outline: none; border: 1px solid #0b9ce1; padding: 5px 15px; margin: 0 8px; border-radius: 5px; } </style> </head> <body> <div id="outer"> <p>123</p> <p>123</p> </div> <label><input id="message"></label> <button id="send">發送</button> <button id="quite">斷開</button> </body> <script src="../lib/jquery.min.js"></script> <script> function log(msg) { $('#outer').append('<p>' + msg + '</p>').scrollTop(500) } function send() { var text = $('#message').val(); if (!text) { alert('Message can not be empty!'); return; } try { socket.send(text); log('Send : ' + text); $('#message').val('').focus() } catch (e) { log(e) } } function quit() { log("Bye!"); socket.close(); socket = null; } var socket = null; function init() { //聲明host注意:是ws協議 var host = "ws://echo.websocket.org/"; try { //新創建一個socket對象 socket = new WebSocket(host); //將連接的狀態信息顯示在log log('WebSocket - status ' + socket.readyState); //監聽打開連接 socket.onopen = function (msg) { log("Welcome - status " + this.readyState); }; //監聽當接收信息時觸發匿名函數 socket.onmessage = function (msg) { log("Received : " + msg.data); }; //關閉連接 socket.onclose = function (msg) { log("Disconnected - status " + this.readyState); }; } catch (e) { log(ex) } $('#message').focus(); } $(function () { init(); $("#message").keypress(function (e) { if (event.keyCode === 13) { send(); } }); $('#send').click(function () { send(); }); $('#quite').click(function () { quite(); }); $("#outer").scroll(function(){ $(this) }) }) </script> </html>

更多關於socket io等的例子和方案看這里

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM