即時通訊基礎(chǔ)(二)

Socket

Socket是應(yīng)用層與TCP/IP協(xié)議族通信的中間軟件抽象層,它是一組接口。



常見的socket類型有兩種:流式Socket和數(shù)據(jù)報式Socket。流式是一種面向連接的Socket,針對于面向連接的TCP服務(wù)應(yīng)用;數(shù)據(jù)報式Socket是一種無連接的Socket,對應(yīng)于無連接的UDP服務(wù)應(yīng)用。


TCP與UDP的區(qū)別

建立連接的的方式
  • TCP
(1)第一次握手:

Client將標志位SYN置為1,隨機產(chǎn)生一個值seq=X,并將該數(shù)據(jù)包發(fā)送給Server,Client進入SYN_SENT狀態(tài),等待Server確認。

(2)第二次握手:

Server收到數(shù)據(jù)包后由標志位SYN=1知道Client請求建立連接,Server將標志位SYN和ACK都置為1,ack=X+1,隨機產(chǎn)生一個值seq=Y,并將該數(shù)據(jù)包發(fā)送給Client以確認連接請求,Server進入SYN_RCVD狀態(tài)。

(3)第三次握手:

Client收到確認后,檢查ack是否為X+1,ACK是否為1,如果正確則將標志位ACK置為1,ack=Y+1,并將該數(shù)據(jù)包發(fā)送給Server,Server檢查ack是否為Y+1,ACK是否為1,如果正確則連接建立成功,Client和Server進入ESTABLISHED狀態(tài),完成三次握手,隨后Client與Server之間可以開始傳輸數(shù)據(jù)了。

(1)第一次揮手:

Client發(fā)送一個FIN,用來關(guān)閉Client到Server的數(shù)據(jù)傳送,Client進入FIN_WAIT_1狀態(tài)。

(2)第二次揮手:

Server收到FIN后,發(fā)送一個ACK給Client,確認序號為收到序號+1(與SYN相同,一個FIN占用一個序號),Server進入CLOSE_WAIT狀態(tài)。

(3)第三次揮手:

Server發(fā)送一個FIN,用來關(guān)閉Server到Client的數(shù)據(jù)傳送,Server進入LAST_ACK狀態(tài)。

(4)第四次揮手:

Client收到FIN后,Client進入TIME_WAIT狀態(tài),接著發(fā)送一個ACK給Server,確認序號為收到序號+1,Server進入CLOSED狀態(tài),完成四次揮手。

為什么建立連接是三次握手,而關(guān)閉連接卻是四次揮手呢?

這是因為服務(wù)端在LISTEN狀態(tài)下,收到建立連接請求的SYN報文后,把ACK和SYN放在一個報文里發(fā)送給客戶端。而關(guān)閉連接時,當(dāng)收到對方的FIN報文時,僅僅表示對方不再發(fā)送數(shù)據(jù)了但是還能接收數(shù)據(jù),己方也未必全部數(shù)據(jù)都發(fā)送給對方了,所以己方可以立即close,也可以發(fā)送一些數(shù)據(jù)給對方后,再發(fā)送FIN報文給對方來表示同意現(xiàn)在關(guān)閉連接,因此,己方ACK和FIN一般都會分開發(fā)送。

  • UDP

我們都知道 TCP 是面向連接的、可靠的、有序的傳輸層協(xié)議,而 UDP 是面向數(shù)據(jù)報的、不可靠的、無序的傳輸協(xié)議,所以 UDP 壓根不會建立什么連接。

就好比發(fā)短信一樣,UDP 只需要知道對方的 ip 地址,將數(shù)據(jù)報一份一份的發(fā)送過去就可以了,其他的作為發(fā)送方,都不需要關(guān)心。


數(shù)據(jù)發(fā)送方式的差異

TCP:由于 TCP 是建立在兩端連接之上的協(xié)議,所以理論上發(fā)送的數(shù)據(jù)流不存在大小的限制。但是由于緩沖區(qū)有大小限制,所以你如果用 TCP 發(fā)送一段很大的數(shù)據(jù),可能會截斷成好幾段,接收方依次的接收。

UDP:由于 UDP 本身發(fā)送的就是一份一份的數(shù)據(jù)報,所以自然而然的就有一個上限的大小。


數(shù)據(jù)有序性的差異

TCP:對于 TCP 來說,本身 TCP 有著超時重傳、錯誤重傳、還有等等一系列復(fù)雜的算法保證了 TCP 的數(shù)據(jù)是有序的,假設(shè)你發(fā)送了數(shù)據(jù) 1、2、3,則只要發(fā)送端和接收端保持連接時,接收端收到的數(shù)據(jù)始終都是 1、2、3。

UDP:而 UDP 協(xié)議則要奔放的多,無論 server 端無論緩沖池的大小有多大,接收 client 端發(fā)來的消息總是一個一個的接收。并且由于 UDP 本身的不可靠性以及無序性,如果 client 發(fā)送了 1、2、3 這三個數(shù)據(jù)報過來,server 端接收到的可能是任意順序、任意個數(shù)三個數(shù)據(jù)報的排列組合。


可靠性的差異

TCP:TCP 內(nèi)部的很多算法機制讓他保持連接的過程中是很可靠的。比如:TCP 的超時重傳、錯誤重傳、TCP 的流量控制、阻塞控制、慢熱啟動算法、擁塞避免算法、快速恢復(fù)算法 等等。所以 TCP 是一個內(nèi)部原理復(fù)雜,但是使用起來比較簡單的這么一個協(xié)議。

UDP:UDP 是一個面向非連接的協(xié)議,UDP 發(fā)送的每個數(shù)據(jù)報帶有自己的 IP 地址和接收方的 IP 地址,它本身對這個數(shù)據(jù)報是否出錯,是否到達不關(guān)心,只要發(fā)出去了就好了。


使用場景
  • UDP

對實時性要求高:比如實時會議,實時視頻這種情況下,如果使用 TCP,當(dāng)網(wǎng)絡(luò)不好發(fā)生重傳時,畫面肯定會有延時,甚至越堆越多。如果使用 UDP 的話,即使偶爾丟了幾個包,但是也不會影響什么,這種情況下使用 UDP 比較好;
多點通信:TCP 需要保持一個長連接,那么在涉及多點通訊的時候,肯定需要和多個通信節(jié)點建立其雙向連接,然后有時在NAT環(huán)境下,兩個通信節(jié)點建立其直接的 TCP 連接不是一個容易的事情,而 UDP 可以無需保持連接,直接發(fā)就可以了,所以成本會很低,而且穿透性好。這種情況下使用 UDP 也是沒錯的。

  • TCP

其他場景,基本都是TCP更加適合。


第三方庫

CocoaAsyncSocket:https://github.com/robbiehanson/CocoaAsyncSocket

CocoaAsyncSocket provides easy-to-use and powerful asynchronous socket libraries for Mac and iOS. The classes are described below.


參考鏈接:
http://www.ruanyifeng.com/blog/2017/06/tcp-protocol.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容