該篇文章主要回顧–TCP/IP協議族中的TCP/UDP、HTTP;還有Socket。(--該文很乾,醞釀了許久!你能耐心看完嗎?O_o)html
我在這個文章中,列舉了常見的TCP/IP族中的協議,今天主角是--傳輸層協議。git
傳輸層(Transport Layer)是OSI(七層模型)中最重要、最關鍵的一層,它負責整體的數據傳輸和數據控制的一層,傳輸層提供端到端(應用會在網卡註冊一個端口號)的交換數據的機制,檢查分組編號與次序。傳輸層對其上三層如會話層等,提供可靠的傳輸服務,對網絡層提供可靠的目的地站點信息。程序員
傳輸層它爲應用層提供會話和數據報通訊服務。github
傳輸層承擔OSI傳輸層的職責。數據庫
傳輸層的核心協議是TCP和UDP。
apache
TCP提供一對一的、面向鏈接的可靠通訊服務。TCP創建鏈接,對發送的數據包進行排序和確認,並恢復在傳輸過程當中丟失的數據包。與TCP不一樣,UDP提供一對一或一對多的、無鏈接的不可靠通訊服務。
不管是TCP/IP仍是在OSI參考模型中,任意相鄰兩層的下層爲服務提供者,上層爲服務調用者。下層爲上層提供的服務可分爲兩類:面向鏈接服務和無鏈接服務。編程
面向鏈接的網絡服務
swift
面向鏈接的網絡服務又稱爲虛電路(Virtual Circuit)服務,它具備網絡鏈接創建、數據傳輸和網絡鏈接釋放三個階段。是按順序傳輸可靠的報文分組方式,適用於指定對象、長報文、會話型傳輸要求。
面向鏈接服務以電話系統爲模式。要和某我的通話,首先拿起電話,撥號碼,通話,而後掛斷。一樣在使用面向鏈接的服務時,用戶首先要創建鏈接,使用鏈接,而後釋放鏈接。鏈接本質上像個管道:發送者在管道的一端放入物體,接收者在另外一端按一樣的次序取出物體;其特色是收發的數據不只順序一致,並且內容也相同。–相似打電話瀏覽器
無鏈接的網絡服務
緩存
無鏈接網絡服務的兩實體之間的通訊不須要事先創建好一個鏈接。無鏈接網絡服務有3種類型:數據報(Datagram)、確認交付(Confirmed Delivery)與請求回答(Request reply)。
無鏈接服務以郵政系統爲模式。每一個報文(信件)帶有完整的目的地址,而且每個報文都獨立於其餘報文,由系統選定的路線傳遞。在正常狀況下,當兩個報文發往同一目的地時,先發的先到。可是,也有可能先發的報文在途中延誤了,後發的報文反而先收到;而這種狀況在面向鏈接的服務中是絕對不可能發生的。–相似發短信
TCP全稱是Transmission Control Protocol,中文名爲傳輸控制協議,它能夠提供可靠的、面向鏈接的網絡數據傳遞服務。傳輸控制協議主要包含下列任務和功能:
確保IP數據報的成功傳遞。
對程序發送的大塊數據進行分段和重組。
確保正確排序及按順序傳遞分段的數據。
經過計算校驗和,進行傳輸數據的完整性檢查。
根據數據是否接收成功發送確定消息。經過使用選擇性確認,也對沒有收到的數據發送否認確認。
爲必須使用可靠的、基於會話的數據傳輸程序,如客戶端/服務器數據庫和電子郵件程序,提供首選傳輸方法。
TCP工做原理
TCP的鏈接創建過程又稱爲TCP三次握手;
首先發送方主機向接收方主機發起一個創建鏈接的同步(SYN)請求;
接收方主機在收到這個請求後向發送方主機回覆一個同步/確認(SYN/ACK)應答;
發送方主機收到此包後再向接收方主機發送一個確認(ACK),此時TCP鏈接成功創建.
一旦初始的三次握手完成,在發送和接收主機之間將按順序發送和確認段。關閉鏈接以前,TCP使用相似的握手過程驗證兩個主機是否都完成發送和接收所有數據。
完成三次握手,客戶端與服務器開始傳送數據。
三次握手示意圖:
三次握手.png
TCP工做過程比較複雜,包括的內容以下。
TCP鏈接關閉:發送方主機和目的主機創建TCP鏈接並完成數據傳輸後,會發送一個將結束標記置1的數據包,以關閉這個TCP鏈接,並同時釋放該鏈接佔用的緩衝區空間。
TCP重置:TCP容許在傳輸的過程當中忽然中斷鏈接。
TCP數據排序和確認*:在傳輸的過程當中使用序列號和確認號來跟蹤數據的接收狀況。
TCP重傳:在TCP的傳輸過程當中,若是在重傳超時時間內沒有收到接收方主機對某數據包的確認回覆,發送方主機就認爲此數據包丟失,並再次發送這個數據包給接收方。
TCP延遲確認:TCP並不老是在接收到數據後當即對其進行確認,它容許主機在接收數據的同時發送本身的確認信息給對方。
TCP數據保護(校驗):TCP是可靠傳輸的協議,它提供校驗和計算來實現數據在傳輸過程當中的完整性。
UDP全稱是User Datagram Protocol,中文名爲用戶數據報協議。UDP 提供無鏈接的網絡服務,該服務對消息中傳輸的數據提供不可靠的、最大努力傳送。這意味着它不保證數據報的到達,也不保證所傳送數據包的順序是否正確。
我最初就有一個疑惑:「既然UDP是一種不可靠的網絡協議,那麼還有什麼使用價值或必要呢?」
在有些狀況下UDP可能會變得很是有用。由於UDP具備TCP所可望不可即的速度優點。雖然TCP中植入了各類安全保障功能,可是在實際執行的過程當中會佔用大量的系統開銷,無疑使速度受到嚴重的影響。反觀UDP因爲排除了信息可靠傳遞機制,將安全和排序等功能移交給上層應用來完成,極大地下降了執行時間,使速度獲得了保證。
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,HyperText Transfer Protocol)是互聯網上應用最爲普遍的一種網絡協議。
http協議規定了客戶端和服務器之間的數據傳輸格式.
http優勢:
簡單快速:
http協議簡單,通訊速度很快;
靈活:
http協議容許傳輸任意類型的數據;
短鏈接:
http協議限制每次鏈接只處理一個請求,服務器對客戶端的請求做出響應後,立刻斷開鏈接.這種方式能夠節省傳輸時間.
請求:客戶端向服務器索要數據.
http協議規定:一個完整的http請求包含’請求行’,'請求頭’,'請求體’三個部分;
請求行:包含了請求方法,請求資源路徑,http協議版本. 「GET /resources/images/ HTTP/1.1″
請求頭:包含了對客戶端的環境描述,客戶端請求的主機地址等信息.
Accept: text/html ( 客戶端所能接收的數據類型 )
Accept-Language: zh-cn ( 客戶端的語言環境 )
Accept-Encoding: gzip( 客戶端支持的數據壓縮格式 )
Host: m.baidu.com( 客戶端想訪問的服務器主機地址 )
User-Agent: Mozilla/5.0(Macintosh;Intel Mac OS X10.10 rv:37.0) Gecko/20100101Firefox/37.0( 客戶端的類型,客戶端的軟件環境 )
請求體:客戶端發給服務器的具體數據,好比文件/圖片等.
響應:服務器返回客戶端想要的數據
http協議規定:一個完整的http響應包含’狀態行’,'響應頭’,'實體內容’三個部分;
狀態行:包含了http協議版本,狀態嗎,狀態英文名稱.
「HTTP/1.1 200 OK」
響應頭:包含了對服務器的描述,對返回數據的描述.
Content-Encoding: gzip(服務器支持的數據壓縮格式) Content-Length: 1528(返回數據的長度)
Content-Type:application/xhtml+xml;(返回數據的類型)
Date: Mon,15Jun201509:06:46GMT(響應的時間) Server: apache (服務器類型)
實體內容:服務器返回給客戶端的具體數據(圖片/html/文件…).
發送http請求
在iOS開發中,發送http請求的方案有不少,常見的有以下幾種:
蘋果原生:
NSURLConnection:
用法簡單,古老經典的一種方案.
NSURLSession:
iOS7之後推出的技術,功能NSURLConnection更增強大.
CFNetWork:NSURL的底層,純C語言,通常不用.
第三方框架:
AFNetWorking(OC);Alamofire(swift);
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:服務端錯誤,服務器不能正確執行一個正確的請求;
詳細描述:狀態碼
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 加一個端口(在網卡註冊的,還記得吧)綁定。
在同一個設備上,兩個進程若是須要進行通信最基本的一個前提能可以惟一的標示一個進程,在本地進程通信中可使用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
建立服務器Socket
鏈接到服務器(Socket編程)
發送數據給服務器
接收服務器返回的數據
關閉Socket : close(socketNumber)
一張經典的Socket C/S的步驟圖。
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
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
一、監聽 6666端口
二、connettion;
三、發送socket
;服務器接收到socket
;
四、服務端send :hello socket;
操做步驟.gif
提供一些服務
將這個服務與本身的IP地址、端口綁定
監放任何到這個IP+端口的TCP請求
接受/拒絕創建這個TCP鏈接
讀寫
斷開TCP鏈接
問啊-一鍵呼叫程序員答題神器,牛人一對一服務,開發者編程必備官方網站:www.wenaaa.com
QQ羣290551701 彙集不少互聯網精英,技術總監,架構師,項目經理!開源技術研究,歡迎業內人士,大牛及新手有志於從事IT行業人員進入!