iOS 的 TCP/IP 協議族剖析 && Socket,iostcp
簡介
該篇文章主要回顧–TCP/IP協議族中的TCP/UDP、HTTP;還有Socket。(--該文很乾,醞釀了許久!你能耐心看完嗎?O_o)
我在這個文章中,列舉了常見的TCP/IP族中的協議,今天主角是--傳輸層協議。
傳輸層(Transport Layer)是OSI(七層模型)中最重要、最關鍵的一層,它負責總體的資料轉送和資料控制的一層,傳輸層提供端到端(應用會在網卡註冊一個連接埠號碼)的交換資料的機制,檢查分組編號與次序。傳輸層對其上三層如會話層等,提供可靠的傳輸服務,對網路層提供可靠的目的地網站資訊。
傳輸層中的協議
- 傳輸層它為應用程式層提供會話和資料報通訊服務。
- 傳輸層承擔OSI傳輸層的職責。
- 傳輸層的核心協議是TCP和UDP。
TCP提供一對一的、連線導向的可靠通訊服務。TCP建立串連,對發送的資料包進行排序和確認,並恢複在傳輸過程中丟失的資料包。與TCP不同,UDP提供一對一或一對多的、不需連線的不可靠通訊服務。
不論是TCP/IP還是在OSI參考模型中,任意相鄰兩層的下層為服務提供者,上層為服務調用者。下層為上層提供的服務可分為兩類:連線導向服務和無串連服務。
- 連線導向的網路服務
連線導向的網路服務又稱為虛電路(Virtual Circuit)服務,它具有網路連接建立、資料轉送和網路連接釋放三個階段。是按順序傳輸可靠的報文分組方式,適用於指定對象、長報文、會話型傳輸要求。
連線導向服務以電話系統為模式。要和某個人通話,首先拿起電話,撥號碼,通話,然後掛斷。同樣在使用連線導向的服務時,使用者首先要建立串連,使用串連,然後釋放串連。串連本質上像個管道:寄件者在管道的一端放入物體,接收者在另一端按同樣的次序取出物體;其特點是收發的資料不僅順序一致,而且內容也相同。–類似打電話
- 不需連線的網路服務
無串連網路服務的兩實體之間的通訊不需要事先建立好一個串連。無串連網路服務有3種類型:資料報(Datagram)、確認交付(Confirmed Delivery)與請求回答(Request reply)。
無串連服務以郵政系統為模式。每個報文(信件)帶有完整的目的地址,並且每一個報文都獨立於其他報文,由系統選定的路線傳遞。在正常情況下,當兩個報文發往同一目的地時,先發的先到。但是,也有可能先發的報文在途中延誤了,後發的報文反而先收到;而這種情況在連線導向的服務中是絕對不可能發生的。–類似發簡訊
傳輸控制通訊協定(TCP)
三向交握:
三向交握.png
TCP工作過程比較複雜,包括的內容如下。
- TCP串連關閉:發送方主機和目的主機建立TCP串連並完成資料轉送後,會發送一個將結束標記置1的資料包,以關閉這個TCP串連,並同時釋放該串連佔用的緩衝區空間。
- TCP重設:TCP允許在傳輸的過程中突然中斷串連。
- TCP資料排序和確認*:在傳輸的過程中使用序號和確認號來跟蹤資料的接收情況。
- TCP重傳:在TCP的傳輸過程中,如果在重傳逾時時間內沒有收到接收方主機對某資料包的確認回複,發送方主機就認為此資料包丟失,並再次發送這個資料包給接收方。
- TCP延遲確認:TCP並不總是在接收到資料後立即對其進行確認,它允許主機在接收資料的同時發送自己的確認資訊給對方。
- TCP資料保護(校正):TCP是可靠傳輸的協議,它提供校正和計算來實現資料在傳輸過程中的完整性。
使用者資料包通訊協定(UDP)
UDP全稱是User Datagram Protocol,中文名為使用者資料包通訊協定。UDP 提供不需連線的網路服務,該服務對訊息中傳輸的資料提供不可靠的、最大努力傳送。這意味著它不保證資料報的到達,也不保證所傳送資料包的順序是否正確。
我最初就有一個疑惑:“既然UDP是一種不可靠的網路通訊協定,那麼還有什麼使用價值或必要呢?”
在有些情況下UDP可能會變得非常有用。因為UDP具有TCP所望塵莫及的速度優勢。雖然TCP中植入了各種安全保障功能,但是在實際執行的過程中會佔用大量的系統開銷,無疑使速度受到嚴重的影響。反觀UDP由於排除了資訊可靠傳遞機制,將安全和排序等功能移交給上層應用來完成,極大地降低了執行時間,使速度得到了保證。
TCP與連接埠號碼
TCP和UDP都是IP層面的傳輸協議,是IP與上層之間的處理介面。TCP和UDP連接埠號碼被設計來區分運行在單個裝置上的多重應用程式的IP地址。由於同一台電腦上可能會運行多個網路應用程式,所以電腦需要確保目標電腦上接收源主機資料包的軟體應用程式的正確性,以及響應能夠被發送到源主機的正確應用程式上。該過程正是通過使用TCP或UDP連接埠號碼來實現的。
--即每一個應用都會在網卡上註冊一個連接埠號碼用來區分同一台裝置上應用的之間的通訊
在TCP和UDP頭部分,有“源連接埠”和“目標連接埠”段,主要用於顯示發送和接收過程中的身份識別資訊。IP 位址和連接埠號碼合在一起被稱為“通訊端”。TCP連接埠比較複雜,其工作方式與UDP連接埠不同。UDP連接埠對於基於UDP的通訊作為單一訊息佇列和網路端點來操作,而所有TCP通訊的終點都是唯一的串連。每個TCP串連由兩個端點唯一識別。由於所有TCP串連由兩對 IP 位址和TCP連接埠唯一識別(每個所連主機都有一個地址/連接埠對),因此每個TCP伺服器連接埠都能提供對多個串連的共用訪問
再看一下IP資料包和TCP/UDP的資料包
資料包.png
HTTP協議
超文字傳輸通訊協定 (HTTP)(HTTP,HyperText Transfer Protocol)是互連網上應用最為廣泛的一種網路通訊協定。
http協議規定了用戶端和伺服器之間的資料轉送格式.
- http優點:
簡單快速:
http協議簡單,通訊速度很快;
靈活:
http協議允許傳輸任意類型的資料;
短串連:
http協議限制每次串連只處理一個請求,伺服器對用戶端的請求作出響應後,馬上中斷連線.這種方式可以節省傳輸時間.
http協議的使用http方法
http協議定義了很多方法對應不同的資源操作,其中最常用的是GET和POST方法。
eg:GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT、PATCH
增:PUT
刪:DELETE
改:POST
查:GET
因為GET和POST可以實現上述所有操作,所以,在現實開發中,GET和POST方法使用的最為廣泛,除此以外HEAD請求使用頻率也比較高;
- GET
在請求URL後面以?的形式跟上發給伺服器的參數,參數以”參數名”=”參數值”的形式拼接,多個參數之間用&分隔;
GET的本質是從伺服器得到資料,效率更高.並且GET請求可以被緩衝.
注意:GET的長度是有限制的,不同的瀏覽器有不同的長度限制,一般在2~8K之間;
- POST
POST的本質是向伺服器發送資料,也可以獲得伺服器處理之後的結果,效率不如GET.POST請求不可以被緩衝,每次重新整理之後都需要重新提交表單.
發送給伺服器的參數全部放在’請求體’中;
理論上,POST傳遞的資料量沒有限制.
注意:所有涉及到使用者隱私的資料(密碼/銀行卡號等…)都要用POST的方式傳遞.
- HEAD
HEAD方法通常用在下載檔案之前,擷取遠程伺服器的檔案資訊!相比於GET請求,不會下載檔案資料,只獲得回應標頭資訊!
一般,使用HEAD方法的目的是提前告訴使用者下載檔案的資訊,由使用者確定是否下載檔案!所以, HEAD方法,最好發送同步請求!
響應訊息
1xx:資訊響應類,表示接收到請求並且繼續處理
2xx:處理成功響應類,表示動作被成功接收、理解和接受
3xx:重新導向響應類,為了完成指定的動作,必須接受進一步處理
4xx:用戶端錯誤,客戶請求包含語法錯誤或者是不能正確執行
5xx:服務端錯誤,伺服器不能正確執行一個正確的請求;
詳細描述:狀態代碼
SocketSocket 簡介
- Socket起源於 20 世 紀 80 年代早期,最早由 4.1c BSD UNIX 引入,所以也稱之為“BSD Socket 或者 Berkeley Socket”。BSD Socket 是事實上的網路應用編程介面標準,其它程式設計語言往往也是用與這套(用C寫成的編程介面)類似介面。
- 用 Socket 能夠實現網路上的不同主機之間或同一主機的不同對象之間的資料通訊。所以,現在 Socket 已經是一類通用通訊介面的集合。
大的類型可以分為網路 Socket 和本地 Socket 兩種。
本地上的兩個進程如何通訊?
- 記憶體共用(
munmap()
);
- 訊息和隊列;
- 管道(匿名管道
pipe()
和具名管道mkfifo()
);
- 訊號量(
P V
操作);
- RPC remote protocol control
- 本地Socket;
網路上的兩個進程如何通訊?
本地處理序間通訊(IPC)通過PID(在終端中輸入ps -ef可查看PID)可以唯一確定彼此,然後通過共用記憶體,訊息佇列來通;網路上的兩個進程確定彼此需要IP與連接埠號碼,通過傳輸層(TCP/UDP)協議進行通訊;
這就是網路 Socket 。
socket可以理解為:在TCP/UDP 加一個連接埠(在網卡註冊的,還記得吧)綁定。
網路socket和 本地 Socket對比
- 在同一個裝置上,兩個進程如果需要進行通訊最基本的一個前提能能夠唯一的標示一個進程,在本地進程通訊中可以使用PID來唯一標示一個進程;
- PID只在本地唯一,網路中的兩個進程PID衝突幾率很大,此時顯然不行了,怎麼辦?
IP層的ip地址可以唯一標示主機,而TCP層協議和連接埠號碼可以唯一標示主機的一個進程,所以可以利用ip地址+協議+連接埠號碼唯一標示網路中的一個進程。
Socket通訊就是一種確定了連接埠號碼的TCP/IP通訊,或者說Socket通訊與IP通訊差別就是連接埠確定,協議確定。
用一張圖表達一下:
Socket.png
連接埠的開啟是雙方的,在C/S(Client&&Server)結構的TCP串連中不僅僅要注意到S的連接埠(監聽的),實際上C也開了一個連接埠,而C端的連接埠是動態連接埠,TCP串連建立的時候,C端的連接埠會在三向交握結束後確定,動態開啟一個,這個連接埠不受使用者/程式員的控制。
Socket C 端書寫步驟
一張經典的Socket C/S的步驟圖。
Objective-C
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 |
1. 匯入標頭檔#import <sys/socket.h> //socket相關#import <netinet/in.h> //internet相關#import <arpa/inet.h> //位址解析通訊協定相關2. socket(建立) int socket(int, int, int); /** 參數 第一個int:domain: 協議域,AF_INET(IPV4的網路開發) 第二個int:type: Socket 類型, SOCK_STREAM(TCP)/SOCK_DGRAM(UDP,報文) 第三個int:protocol: IPPROTO_TCP,協議,如果輸入0,可以根據第二個參數,自動選擇協議 傳回值 socket,如果 > 0 就表示成功 */3. connection (串連到“伺服器) connect(int, const struct sockaddr *, socklen_t) /** 參數 1> 用戶端socket 2> 指向資料結構sockaddr的指標,其中包括目的連接埠和IP地址 伺服器的"結構體"地址,C語言沒有對象 3> 結構體資料長度 傳回值 0 成功/其他 錯誤代號 */4. write(發送資料) send(int, const void *, size_t, int) /** 參數 1> 用戶端socket 2> 發送內容地址 void * == id 3> 發送內容長度 4> 發送方式標誌,一般為0 傳回值 如果成功,則返回傳送的位元組數,失敗則返回SOCKET_ERROR */5. read (接收) recv(int, void *, size_t, int) /** 參數 第一個int :建立的socket void *:接收內容的地址 size_t:接收內容的長度 第二個int.:接收資料的標記 0,就是阻塞式,一直等待伺服器的資料 傳回值 接收到的資料長度 */6. close close(int); int:就是建立的socket |
按照上面5個步驟就可以寫一個socket的通訊的小demo:
寫好的已經放在了我的github;
此時沒有寫服務端,怎麼測試?
可利用:nc -lk 連接埠號碼:始終監聽本機電腦此連接埠的資料。
eg:nc -lk 6666;
操作步驟gif
1、監聽 6666連接埠
2、connettion;
3、發送socket
;伺服器接收到socket
;
4、服務端send :hello socket;
操作步驟.gifS端socket通訊步驟