引言
網(wǎng)絡(luò)七層由下往上分別為物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層、會話層、表示層和應(yīng)用層。 其中物理層、數(shù)據(jù)鏈路層和網(wǎng)絡(luò)層通常被稱作媒體層,是網(wǎng)絡(luò)工程師所研究的對象; 傳輸層、會話層、表示層和應(yīng)用層則被稱作主機層,是用戶所面向和關(guān)心的內(nèi)容。
http協(xié)議對應(yīng)于應(yīng)用層
tcp/udp協(xié)議對應(yīng)于傳輸層
ip協(xié)議對應(yīng)于網(wǎng)絡(luò)層
三者本質(zhì)上沒有可比性。何況HTTP協(xié)議是基于TCP連接的。TCP/IP是傳輸層協(xié)議,主要解決數(shù)據(jù)如何在網(wǎng)絡(luò)中傳輸;而HTTP是應(yīng)用層協(xié)議,主要解決如何包裝數(shù)據(jù)。我們在傳輸數(shù)據(jù)時,可以只使用傳輸層(TCP/IP),但是那樣的話,由于沒有應(yīng)用層,便無法識別數(shù)據(jù)內(nèi)容,如果想要使傳輸?shù)臄?shù)據(jù)有意義,則必須使用應(yīng)用層協(xié)議,應(yīng)用層協(xié)議很多,有HTTP、FTP、TELNET等等,也可以自己定義應(yīng)用層協(xié)議。WEB使用HTTP作傳輸層協(xié)議,以封裝HTTP文本信息,然后使用TCP/IP做傳輸層協(xié)議將它發(fā)送到網(wǎng)絡(luò)上。Socket是對TCP/IP協(xié)議的封裝,Socket本身并不是協(xié)議,而是一個調(diào)用接口(API),通過Socket,我們才能使用TCP/IP協(xié)議。
一、TCP
TCP是面向連接的、傳輸可靠(保證數(shù)據(jù)正確性且保證數(shù)據(jù)順序)、用于傳輸大量數(shù)據(jù)(流模式)、速度慢,建立連接需要開銷較多(時間,系統(tǒng)資源)。TCP是一種流模式的協(xié)議,是面向連接的,也就是說,在連接持續(xù)的過程中,socket中收到的數(shù)據(jù)都是由同一臺主機發(fā)出的(劫持什么的不考慮),因此,知道保證數(shù)據(jù)是有序的到達(dá)就行了,至于每次讀取多少數(shù)據(jù)不關(guān)心。
TCP客戶端-服務(wù)器程序設(shè)計基本框架

TCP三次握手
所謂三次握手(Three-way Handshake),是指建立一個TCP連接時,需要客戶端和服務(wù)器總共發(fā)送3個包。三次握手的目的是連接服務(wù)器指定端口,建立TCP連接,并同步連接雙方的序列號和確認(rèn)號并交換TCP窗口大小信息。在socket編程中,客戶端執(zhí)行connect()時,將觸發(fā)三次握手

SYN(synchronous)是同步標(biāo)志;ACK (Acknowledgement)是確認(rèn)標(biāo)志,seq是序列號。?
第一次握手:客戶端發(fā)送一個TCP的SYN標(biāo)志位置1的包,指明客戶打算連接的服務(wù)器的端口,以及初始序號X,保存在包頭的序列號字段里。?
第二次握手:服務(wù)器發(fā)回確認(rèn)包(ACK)應(yīng)答。即SYN標(biāo)志位和ACK標(biāo)志位均為1同時,將確認(rèn)序號設(shè)置為客戶的序列號加1以,即X+1。?
第三次握手:客戶端再次發(fā)送確認(rèn)包(ACK) SYN標(biāo)志位為0,ACK標(biāo)志位為1。并且把服務(wù)器發(fā)來ACK的序號字段+1,放在確定字段中發(fā)送給對方.并且在數(shù)據(jù)段放寫序列號的+1。
TCP四次揮手
?三次握手耳熟能詳,四次揮手估計就不怎么明白了,所謂四次揮手(Four-Way Wavehand)即終止TCP連接,就是指斷開一個TCP連接時,需要客戶端和服務(wù)端總共發(fā)送4個包以確認(rèn)連接的斷開。在socket編程中,這一過程由客戶端或服務(wù)端任一方執(zhí)行close來觸發(fā)
四次揮手的流程:

?由于TCP連接時全雙工的,因此,每個方向都必須要單獨進(jìn)行關(guān)閉,這一原則是當(dāng)一方完成數(shù)據(jù)發(fā)送任務(wù)后,發(fā)送一個FIN來終止這一方向的連接,收到一個FIN只是意味著這一方向上沒有數(shù)據(jù)流動了,即不會再收到數(shù)據(jù)了,但是在這個TCP連接上仍然能夠發(fā)送數(shù)據(jù),直到這一方向也發(fā)送了FIN。首先進(jìn)行關(guān)閉的一方將執(zhí)行主動關(guān)閉,而另一方則執(zhí)行被動關(guān)閉,上圖描述的即是如此。
(1)第一次揮手:Client發(fā)送一個FIN,用來關(guān)閉Client到Server的數(shù)據(jù)傳送,Client進(jìn)入FIN_WAIT_1狀態(tài)。
(2)第二次揮手:Server收到FIN后,發(fā)送一個ACK給Client,確認(rèn)序號為收到序號+1(與SYN相同,一個FIN占用一個序號),Server進(jìn)入CLOSE_WAIT狀態(tài)。
(3)第三次揮手:Server發(fā)送一個FIN,用來關(guān)閉Server到Client的數(shù)據(jù)傳送,Server進(jìn)入LAST_ACK態(tài)。
(4)第四次揮手:Client收到FIN后,Client進(jìn)入TIME_WAIT狀態(tài),接著發(fā)送一個ACK給Server,確認(rèn)序號為收到序號+1,Server進(jìn)入CLOSED狀態(tài),完成四次揮手。
上面是一方主動關(guān)閉,另一方被動關(guān)閉的情況,實際中還會出現(xiàn)同時發(fā)起主動關(guān)閉的情況,具體流程如下圖:

流程和狀態(tài)在上圖中已經(jīng)很明了了,在此不再贅述,可以參考前面的四次揮手解析步驟。
注意
關(guān)于三次握手與四次揮手通常都會有典型的面試題,在此提出供有需求的XDJM們參考:
? ? (1)三次握手是什么或者流程?四次握手呢?答案前面分析就是。
? ? (2)為什么建立連接是三次握手,而關(guān)閉連接卻是四次揮手呢?
當(dāng)Server端收到Client端的SYN連接請求報文后,可以直接發(fā)送SYN+ACK報文。其中ACK報文是用來應(yīng)答的,SYN報文是用來同步的。但是關(guān)閉連接時,當(dāng)Server端收到FIN報文時,很可能并不會立即關(guān)閉SOCKET,所以只能先回復(fù)一個ACK報文,告訴Client端,”你發(fā)的FIN報文我收到了”。只有等到我Server端所有的報文都發(fā)送完了,我才能發(fā)送FIN報文,因此不能一起發(fā)送。故需要四步握手。
二、UDP?
UDP是面向無連接、傳輸不可靠、用于傳輸少量數(shù)據(jù)(數(shù)據(jù)包模式)、速度快的傳輸層協(xié)議。注意,UDP傳輸?shù)氖菙?shù)據(jù)報包,而TCP是流。?
UDP是面向無連接的協(xié)議,只要知道接收端的IP和端口,且網(wǎng)絡(luò)是可達(dá)的,任何主機都可以向接收端發(fā)送數(shù)據(jù)。這時候,如果一次能讀取超過一個報文的數(shù)據(jù),則會亂套。比如,主機A向發(fā)送了報文P1,主機B發(fā)送了報文P2,如果能夠讀取超過一個報文的數(shù)據(jù),那么就會將P1和P2的數(shù)據(jù)合并在了一起,這樣的數(shù)據(jù)是沒有意義的。
基本UDP客戶—服務(wù)器程序設(shè)計基本框架流程圖

三、什么是Socket?
Socket又稱之為“套接字”,是系統(tǒng)提供的用于網(wǎng)絡(luò)通信的方法。它的實質(zhì)并不是一種協(xié)議,沒有規(guī)定計算機應(yīng)當(dāng)怎么樣傳遞消息,只是給程序員提供了一個發(fā)送消息的接口,程序員使用這個接口提供的方法,發(fā)送與接收消息。
Socket描述了一個IP、端口對。它簡化了程序員的操作,知道對方的IP以及PORT就可以給對方發(fā)送消息,再由服務(wù)器端來處理發(fā)送的這些消息。所以,Socket一定包含了通信的雙方,即客戶端(Client)與服務(wù)端(server)。
Socket的通信過程
每一個應(yīng)用或者說服務(wù)都有一個端口。比如DNS的端口號53,http的端口號80都是對應(yīng)一個應(yīng)用或者服務(wù)的端口。我們能由DNS請求到查詢信息,是因為DNS服務(wù)器時時刻刻都在監(jiān)聽53端口,當(dāng)收到我們的查詢請求以后,就能夠返回我們想要的IP信息。所以,從程序設(shè)計上來講,應(yīng)該包含以下步驟:
(1)服務(wù)端利用Socket監(jiān)聽端口;
(2)客戶端發(fā)起連接;
(3)服務(wù)端返回信息,建立連接,開始通信;
(4)客戶端,服務(wù)端斷開連接。
Socket原理
Socket是通訊的根本,是支持TCP/IP協(xié)議的網(wǎng)絡(luò)通信的基本操作單元。它是網(wǎng)絡(luò)通信過程中端點的抽象表示,包含進(jìn)行網(wǎng)絡(luò)通信必須的五種信息:連接使用的協(xié)議,本地主機地址的IP地址,本地進(jìn)程的協(xié)議端口,遠(yuǎn)地主機的IP地址,遠(yuǎn)地進(jìn)程的協(xié)議端口。
應(yīng)用層通過傳輸層進(jìn)行數(shù)據(jù)通信時,TCP會遇到同時為多個應(yīng)用程序進(jìn)程提供并發(fā)服務(wù)的問題。多個TCP連接或多個應(yīng)用程序進(jìn)程可能需要通過同一個TCP協(xié)議端口傳輸數(shù)據(jù)。為了區(qū)別不同的應(yīng)用程序和連接,許多計算機操作系統(tǒng)為應(yīng)用程序與TCP/IP協(xié)議交互提供了Socket接口。應(yīng)用層可以和傳輸層通過Socket接口,區(qū)分來自不同應(yīng)用程序進(jìn)程或網(wǎng)絡(luò)連接的通信,實現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務(wù)。
Socket連接
建立Socket連接至少需要一對套接字,其中一個運行于客戶端,稱為ClientSocket,另一個運行于服務(wù)器端,稱為ServerSocket。
套接字之間的連接過程分為三個步驟:
(1)服務(wù)器監(jiān)聽:服務(wù)器端套接字并不定位具體的客戶端套接字,而是處于等待連接的狀態(tài),實時監(jiān)控網(wǎng)絡(luò)狀態(tài),等待客戶端的連接請求
(2)客戶端請求:指客戶端的套接字提出連接請求,要連接的目標(biāo)是服務(wù)器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務(wù)器的套接字,指出服務(wù)器端套接字的地址和端口號,然后就向服務(wù)器端套接字提出連接請求
(3)連接確認(rèn):當(dāng)服務(wù)器端套接字監(jiān)聽到或者說接收到客戶端套接字的連接請求時,就響應(yīng)客戶端套接字的請求,建立一個新的線程,把服務(wù)器端套接字的描述發(fā)給客戶端,一旦客戶端確認(rèn)了此描述,雙方就正式建立連接。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽狀態(tài),繼續(xù)接收其他客戶端套接字的連接請求

Socket傳輸?shù)氖亲止?jié)流,AsyncSocke封裝的庫以NSData的形式傳輸。