什么是socket?
Socket 其實(shí)并不是一個協(xié)議。它工作在 OSI 模型會話層(第5層),是為了方便大家直接使用更底層協(xié)議(一般是TCP 或 UDP )而存在的一個抽象層。Socket是對TCP/IP協(xié)議的封裝,Socket本身并不是協(xié)議,而是一個調(diào)用接口(API)。

Socket通常也稱作”套接字”,用于描述IP地址和端口,是一個通信鏈的句柄。網(wǎng)絡(luò)上的兩個程序通過一個雙向的通訊連接實(shí)現(xiàn)數(shù)據(jù)的交換,這個雙向鏈路的一端稱為一個Socket,一個Socket由一個IP地址和一個端口號唯一確定。應(yīng)用程序通常通過”套接字”向網(wǎng)絡(luò)發(fā)出請求或者應(yīng)答網(wǎng)絡(luò)請求。
Socket在通訊過程中,服務(wù)端監(jiān)聽某個端口是否有連接請求,客戶端向服務(wù)端發(fā)送連接請求,服務(wù)端收到連接請求向客戶端發(fā)出接收消息,這樣一個連接就建立起來了。客戶端和服務(wù)端也都可以相互發(fā)送消息與對方進(jìn)行通訊,直到雙方連接斷開。
什么是WebSocket?
Websocket是應(yīng)用層第七層上的一個應(yīng)用層協(xié)議,它必須依賴 HTTP 協(xié)議進(jìn)行一次握手 ,握手成功后,數(shù)據(jù)就直接從 TCP 通道傳輸,與 HTTP 無關(guān)了。
Websocket的數(shù)據(jù)傳輸是frame形式傳輸?shù)?,比如會將一條消息分為幾個frame,按照先后順序傳輸出去。這樣做會有幾個好處:
1 大數(shù)據(jù)的傳輸可以分片傳輸,不用考慮到數(shù)據(jù)大小導(dǎo)致的長度標(biāo)志位不足夠的情況。
2 和http的chunk一樣,可以邊生成數(shù)據(jù)邊傳遞消息,即提高傳輸效率。
SocketRocket框架
使用cocoapods導(dǎo)入SocketRocket框架
platform :ios,"7.0"
target "WebScoketTest" do
pod 'SocketRocket'
end
框架并不開源,我們只能看到對外封裝的一些方法。
一部分為SRWebSocket的初始化,以及連接,關(guān)閉連接,發(fā)送消息等方法。另一部分為SRWebSocketDelegate,其中包括一些回調(diào):收到消息的回調(diào),連接失敗的回調(diào),關(guān)閉連接的回調(diào),收到pong的回調(diào),是否需要把data消息轉(zhuǎn)換成string的代理方法。
使用框架
點(diǎn)擊下載例子
其中包括了一個簡單的心跳,重連機(jī)制和websocket封裝好的pingpong機(jī)制
部分代碼:


(1)什么是心跳?
簡單的來說,心跳就是用來檢測TCP連接的雙方是否可用。那又會有人要問了,TCP不是本身就自帶一個KeepAlive機(jī)制嗎?
?這里我們需要說明的是TCP的KeepAlive機(jī)制只能保證連接的存在,但是并不能保證客戶端以及服務(wù)端的可用性.
?我們客戶端發(fā)起心跳Ping(一般都是客戶端),假如設(shè)置在10秒后如果沒有收到回調(diào),那么說明服務(wù)器或者客戶端某一方出現(xiàn)問題,這時候我們需要主動斷開連接。
?服務(wù)端也是一樣,會維護(hù)一個socket的心跳間隔,當(dāng)約定時間內(nèi),沒有收到客戶端發(fā)來的心跳,我們會知道該連接已經(jīng)失效,然后主動斷開連接。
?國內(nèi)移動無線網(wǎng)絡(luò)運(yùn)營商在鏈路上一段時間內(nèi)沒有數(shù)據(jù)通訊后, 會淘汰NAT表中的對應(yīng)項(xiàng), 造成鏈路中斷。而國內(nèi)的運(yùn)營商一般NAT超時的時間為5分鐘,所以通常我們心跳設(shè)置的時間間隔為3-5分鐘。
(2)什么是pingpong機(jī)制?

? 當(dāng)服務(wù)端發(fā)出一個Ping,客戶端沒有在約定的時間內(nèi)返回響應(yīng)的ack,則認(rèn)為客戶端已經(jīng)不在線,這時我們Server端會主動斷開Scoket連接,并且改由APNS推送的方式發(fā)送消息。
? 同樣的是,當(dāng)客戶端去發(fā)送一個消息,因?yàn)槲覀冞t遲無法收到服務(wù)端的響應(yīng)ack包,則表明客戶端或者服務(wù)端已不在線,我們也會顯示消息發(fā)送失敗,并且斷開Scoket連接。
? 還記得我們之前CocoaSyncSockt的例子所講的獲取消息超時就斷開嗎?其實(shí)它就是一個PingPong機(jī)制的客戶端實(shí)現(xiàn)。我們每次可以在發(fā)送消息成功后,調(diào)用這個超時讀取的方法,如果一段時間沒收到服務(wù)器的響應(yīng),那么說明連接不可用,則斷開Scoket連接
(3)什么是重連機(jī)制?
理論上,我們自己主動去斷開的Scoket連接(例如退出賬號,APP退出到后臺等等),不需要重連。其他的連接斷開,我們都需要進(jìn)行斷線重連。
?一般解決方案是嘗試重連幾次,如果仍舊無法重連成功,那么不再進(jìn)行重連。
webSocket服務(wù)端的實(shí)現(xiàn)
(1)安裝Homebrew
終端運(yùn)行:
// 鏈接1
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
(2)成功后,安裝node
$ brew install node
(3)安裝ws模塊
$ npm install ws
此時如果出現(xiàn)錯誤
npm WARN enoent ENOENT: no such file or directory
可以使用$ npm init -f命令生成一下
(4)cd到下載的js文件路徑下
執(zhí)行$ node 文件名.js
此時運(yùn)行下載的demo,試試看吧!