1. 程式人生 > >iOS Client 與WebSocket 通訊(一)

iOS Client 與WebSocket 通訊(一)

         這一篇我們先了解一下基本知識,這樣對我們後面的學習更加有幫助  。

          Socket,WebSocket,Http,Tcp等這些我們已經聽的耳朵有繭了,但是用得時候還是複習一下吧。

         大學學習網路基礎的時候老師講過,網路由下往上分為物理層、資料鏈路層、網路層、傳輸層、會話層、表示層和應用層。通過初步的瞭解,我知道IP協議對應於網路層,TCP協議對應於傳輸層,而HTTP協議對應於應用層,三者從本質上來說沒有可比性,socket則是對TCP/IP協議的封裝和應用(程式設計師層面上)。也可以說,TPC/IP協議是傳輸層協議,主要解決資料如何在網路中傳輸,而

HTTP是應用層協議,主要解決如何包裝資料。關於TCP/IPHTTP協議的關係,網路有一段比較容易理解的介紹:

     “我們在傳輸資料時,可以只使用(傳輸層)TCP/IP協議,但是那樣的話,如果沒有應用層,便無法識別資料內容,如果想要使傳輸的資料有意義,則必須使用到應用層協議,應用層協議有很多,比如HTTPFTPTELNET等,也可以自己定義應用層協議。WEB使用HTTP協議作應用層協議,以封裝HTTP文字資訊,然後使用TCP/IP做傳輸層協議將它發到網路上。

而我們平時說的最多的socket是什麼呢,實際上socket是對TCP/IP協議的封裝,Socket本身並不是協議,而是一個呼叫介面(

API),通過Socket,我們才能使用TCP/IP協議。實際上,SocketTCP/IP協議沒有必然的聯絡。Socket程式設計介面在設計的時候,就希望也能適應其他的網路協議。所以說,Socket的出現只是使得程式設計師更方便地使用TCP/IP協議棧而已,是對TCP/IP協議的抽象,從而形成了我們知道的一些最基本的函式介面,比如createlistenconnectacceptsendreadwrite等等。網路有一段關於socketTCP/IP協議關係的說法比較容易理解:

         “TCP/IP只是一個協議棧,就像作業系統的執行機制一樣,必須要具體實現,同時還要提供對外的操作介面。這個就像作業系統會提供標準的程式設計介面,比如

win32程式設計介面一樣,TCP/IP也要提供可供程式設計師做網路開發所用的介面,這就是Socket程式設計介面。

關於TCP/IP協議的相關只是,用博大精深來講我想也不為過,單單查一下網上關於此類只是的資料和書籍文獻的數量就知道,這個我打算會買一些經典的書籍(比如《TCP/IP詳解:卷一、卷二、卷三》)進行學習,今天就先總結一些基於基於TCP/IP協議的應用和程式設計介面的知識,也就是剛才說了很多的HTTPSocket

  CSDN上有個比較形象的描述:

               HTTP是轎車,提供了封裝或者顯示資料的具體形式;

               Socket是發動機,提供了網路通訊的能力。

實際上,傳輸層的TCP是基於網路層的IP協議的,而應用層的HTTP協議又是基於傳輸層的TCP協議的,而Socket本身不算是協議,就像上面所說,它只是提供了一個針對TCP或者UDP程式設計的介面。

          下面是一些經常在筆試或者面試中碰到的重要的概念,特在此做摘抄和總結。

一什麼是TCP連線的三次握手

第一次握手:客戶端傳送syn(syn=j)到伺服器,並進入SYN_SEND狀態,等待伺服器確認;第二次握手:伺服器收到syn包,必須確認客戶的SYNack=j+1),同時自己也傳送一個SYN包(syn=k),即SYN+ACK包,此時伺服器進入SYN_RECV狀態;第三次握手:客戶端收到伺服器的SYNACK包,向伺服器傳送確認包ACK(ack=k+1),此包傳送完畢,客戶端和伺服器進入ESTABLISHED狀態,完成三次握手。握手過程中傳送的包裡不包含資料,三次握手完畢後,客戶端與伺服器才正式開始傳送資料。理想狀態下,TCP連線一旦建立,在通訊雙方中的任何一方主動關閉連線之前,TCP連線都將被一直保持下去。斷開連線時伺服器和客戶端均可以主動發起斷開TCP連線的請求,斷開過程需要經過四次握手(過程就不細寫了,就是伺服器和客戶端互動,最終確定斷開)

二利用Socket建立網路連線的步驟

建立Socket連線至少需要一對套接字,其中一個運行於客戶端,稱為ClientSocket,另一個運行於伺服器端,稱為ServerSocket

套接字之間的連線過程分為三個步驟:伺服器監聽,客戶端請求,連線確認。

1、伺服器監聽:伺服器端套接字並不定位具體的客戶端套接字,而是處於等待連線的狀態,實時監控網路狀態,等待客戶端的連線請求。

2、客戶端請求:指客戶端的套接字提出連線請求,要連線的目標是伺服器端的套接字。為此,客戶端的套接字必須首先描述它要連線的伺服器的套接字,指出伺服器端套接字的地址和埠號,然後就向伺服器端套接字提出連線請求。

3、連線確認:當伺服器端套接字監聽到或者說接收到客戶端套接字的連線請求時,就響應客戶端套接字的請求,建立一個新的執行緒,把伺服器端套接字的描述發給客戶端,一旦客戶端確認了此描述,雙方就正式建立連線。而伺服器端套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連線請求。

HTTP連結的特點

        HTTP協議即超文字傳送協議(Hypertext Transfer Protocol ),是Web聯網的基礎,也是手機聯網常用的協議之一,HTTP協議是建立在TCP協議之上的一種應用。

        HTTP連線最顯著的特點是客戶端傳送的每次請求都需要伺服器回送響應,在請求結束後,會主動釋放連線。從建立連線到關閉連線的過程稱為一次連線

四、TCPUDP的區別(考得最多。。快被考爛了我覺得

1、TCP是面向連結的,雖然說網路的不安全不穩定特性決定了多少次握手都不能保證連線的可靠性,但TCP的三次握手在最低限度上(實際上也很大程度上保證了)保證了連線的可靠性;而UDP不是面向連線的,UDP傳送資料前並不與對方建立連線,對接收到的資料也不傳送確認訊號,傳送端不知道資料是否會正確接收,當然也不用重發,所以說UDP是無連線的、不可靠的一種資料傳輸協議。

2、也正由於1所說的特點,使得UDP的開銷更小資料傳輸速率更高,因為不必進行收發資料的確認,所以UDP的實時性更好。

知道了TCPUDP的區別,就不難理解為何採用TCP傳輸協議的MSN比採用UDPQQ傳輸檔案慢了,但並不能說QQ的通訊是不安全的,因為程式設計師可以手動對UDP的資料收發進行驗證,比如傳送方對每個資料包進行編號然後由接收方進行驗證啊什麼的,即使是這樣,UDP因為在底層協議的封裝上沒有采用類似TCP三次握手而實現了TCP所無法達到的傳輸效率。

簡單總結:

HTTP協議:簡單物件訪問協議,對應於應用層HTTP協議是基於TCP連線的。

TCP協議:對應於傳輸層。

IP協議:對應於網路層


TCP/IP
是傳輸層協議,主要解決資料如何在網路中傳輸;而HTTP是應用層協議,主要解決如何包裝資料。

Socket是對TCP/IP協議的封裝,Socket本身並不是協議,而是一個呼叫介面(API),通過Socket,我們才能使用TCP/IP協議。

HTTP連線:HTTP連線就是所謂的短連線,即客戶端向伺服器端傳送一次請求,伺服器端響應後連線即會斷掉;

Socket連線:Socket連線就是所謂的長連線,理論上客戶端和伺服器端一旦建立起連線將不會主動斷掉;但是由於各種環境因素可能會是連線斷開,比如說:伺服器端或客戶端主機down了,網路故障,或者兩者之間長時間沒有資料傳輸,網路防火牆可能會斷開該連線以釋放網路資源。所以當一個Socket連線中沒有資料的傳輸,那麼為了維持連線需要傳送心跳訊息~~具體心跳訊息格式是開發者自己定義的。

WebSocket

          WebSocketHTML5開始提供的一種瀏覽器與伺服器間進行全雙工通訊的網路技術。 WebSocket通訊協定於2011年被IETF定為標準 RFC 6455WebSocketAPIW3C定為標準。

         在WebSocket API中,瀏覽器和伺服器只需要要做一個握手的動作,然後,瀏覽器和伺服器之間就形成了一條快速通道。兩者之間就直接可以資料互相傳送。

現在,很多網站為了實現推送技術,所用的技術都是輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對伺服器發出HTTP request,然後由伺服器返回最新的資料給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器需要不斷的向伺服器發出請求,然而HTTP requestheader是非常長的,裡面包含的資料可能只是一個很小的值,這樣會佔用很多的頻寬和伺服器資源。

        而比較新的技術去做輪詢的效果是Comet,使用了AJAX。但這種技術雖然可達到雙向通訊,但依然需要發出請求,而且在Comet中,普遍採用了長連結,這也會大量消耗伺服器頻寬和資源。

        面對這種狀況,HTML5定義了WebSocket協議,能更好的節省伺服器資源和頻寬並達到實時通訊。

握手協議

在實現Websocket連線過程中,需要透過瀏覽器發出Websocket連線請求,然後伺服器發出迴應,這個過程通常稱為握手” (handshaking)
PS:
後期的版本大多屬於功能上的擴充,例如使用第7版的握手協議同樣也適用於第8版的握手協議。

瀏覽器請求

GET / HTTP/1.1

Upgrade: websocket

Connection: Upgrade

Host: example.com

Origin: null

Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==

Sec-WebSocket-Version: 13

伺服器迴應

HTTP/1.1 101 Switching Protocols

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=

Sec-WebSocket-Origin: null

Sec-WebSocket-Location: ws://example.com/

原理

在請求中的“Sec-WebSocket-Key”是隨機的,伺服器端會用這些資料來構造出一個SHA-1的資訊摘要。

“Sec-WebSocket-Key”加上一個魔幻字串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”。使用 SHA-1 加密,之後進行 BASE-64編碼,將結果做為 “Sec-WebSocket-Accept”頭的值,返回給客戶端。

客戶端的Websocket物件一共綁定了四個事件:

1onopen:連線建立時觸發;

2onmessage:收到服務端訊息時觸發;

3onerror:連接出錯時觸發;

4onclose:連線關閉時觸發;

有了這4個事件,我們就可以很容易很輕鬆的駕馭websocket,並且需要說明的是websocket支援二進位制資料的傳輸,因此,它遠不止聊天室應用這麼簡單。

WebSocket API是下一代客戶端-伺服器的非同步通訊方法。該通訊取代了使用wswss協議的單個的TCP套接字,可用於任意的客戶端和伺服器程式

WebSocket API最偉大之處在於在任意時刻伺服器和客戶端可以相互推送資訊。WebSocket並不限於以Ajax(XHR)方式通訊,Ajax技術需要客戶端發起請求,而WebSocket伺服器和客戶端可以彼此相互推送資訊;XHR受到域的限制,而WebSocket是允許跨域通訊。

在伺服器方面,網上都有不同對websocket支援的伺服器:

       jetty - http://jetty.codehaus.org/jetty/ (版本7開始支援websocket)

          netty - http://www.jboss.org/netty

          ruby - http://github.com/gimite/web-socket-ruby

          Kaazing - http://www.kaazing.org/confluence/display/KAAZING/Home

          Tomcat - http://tomcat.apache.org/ (7.0.26支援websocket)

           node.js - https://github.com/Worlize/WebSocket-Node