深入淺出-TCP/IP協議族剖析&&Socket



#簡介
該篇文章主要回顧–TCP/IP協議族中的TCP/UDP、HTTP;還有Socket。***(--該文很乾,醞釀了許久!你能耐心看完嗎?O_o)***

我在這個文章中,列舉了常見的TCP/IP族中的協議,今天主角是--傳輸層協議。

傳輸層(Transport Layer)是OSI(七層模型)中最重要、最關鍵的一層,它負責總體的數據傳輸和數據控制的一層,傳輸層提供端到端(應用會在網卡註冊一個端口號)的交換數據的機制,檢查分組編號與次序。傳輸層對其上三層如會話層等,提供可靠的傳輸服務,對網絡層提供可靠的目的地站點信息。

#傳輸層中的協議

  • 傳輸層它爲應用層提供會話和數據報通信服務。
  • 傳輸層承擔OSI傳輸層的職責。
  • 傳輸層的核心協議是TCP和UDP。

TCP提供一對一的、面向連接的可靠通信服務。TCP建立連接,對發送的數據包進行排序和確認,並恢復在傳輸過程中丟失的數據包。與TCP不同,UDP提供一對一或一對多的、無連接的不可靠通信服務。
不論是TCP/IP還是在OSI參考模型中,任意相鄰兩層的下層爲服務提供者,上層爲服務調用者。下層爲上層提供的服務可分爲兩類:面向連接服務和無連接服務。

  1. 面向連接的網絡服務

面向連接的網絡服務又稱爲虛電路(Virtual Circuit)服務,它具有網絡連接建立、數據傳輸和網絡連接釋放三個階段。是按順序傳輸可靠的報文分組方式,適用於指定對象、長報文、會話型傳輸要求。
面向連接服務以電話系統爲模式。要和某個人通話,首先拿起電話,撥號碼,通話,然後掛斷。同樣在使用面向連接的服務時,用戶首先要建立連接,使用連接,然後釋放連接。連接本質上像個管道:發送者在管道的一端放入物體,接收者在另一端按同樣的次序取出物體;其特點是收發的數據不僅順序一致,而且內容也相同。–類似打電話

  1. 無連接的網絡服務

無連接網絡服務的兩實體之間的通信不需要事先建立好一個連接。無連接網絡服務有3種類型:數據報(Datagram)、確認交付(Confirmed Delivery)與請求回答(Request reply)。
無連接服務以郵政系統爲模式。每個報文(信件)帶有完整的目的地址,並且每一個報文都獨立於其他報文,由系統選定的路線傳遞。在正常情況下,當兩個報文發往同一目的地時,先發的先到。但是,也有可能先發的報文在途中延誤了,後發的報文反而先收到;而這種情況在面向連接的服務中是絕對不可能發生的。–類似發短信

##傳輸控制協議(TCP)

  1. TCP全稱是Transmission Control Protocol,中文名爲傳輸控制協議,它可以提供可靠的、面向連接的網絡數據傳遞服務。傳輸控制協議主要包含下列任務和功能:
  • 確保IP數據報的成功傳遞。
    • 對程序發送的大塊數據進行分段和重組。
    • 確保正確排序及按順序傳遞分段的數據。
    • 通過計算校驗和,進行傳輸數據的完整性檢查。
    • 根據數據是否接收成功發送肯定消息。通過使用選擇性確認,也對沒有收到的數據發送否定確認。
      爲必須使用可靠的、基於會話的數據傳輸程序,如客戶端/服務器數據庫和電子郵件程序,提供首選傳輸方法。
  1. 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)

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,HyperText Transfer Protocol)是互聯網上應用最爲廣泛的一種網絡協議。
http協議規定了客戶端和服務器之間的數據傳輸格式.

  • http優點:

簡單快速:
http協議簡單,通信速度很快;
靈活:
http協議允許傳輸任意類型的數據;
短連接:
http協議限制每次連接只處理一個請求,服務器對客戶端的請求作出響應後,馬上斷開連接.這種方式可以節省傳輸時間.

##http協議的使用

  1. 請求:客戶端向服務器索要數據.
    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( 客戶端的類型,客戶端的軟件環境 )

  • 請求體:客戶端發給服務器的具體數據,比如文件/圖片等.
  1. 響應:服務器返回客戶端想要的數據
    http協議規定:一個完整的http響應包含’狀態行’,‘響應頭’,'實體內容’三個部分;
  • 狀態行:包含了http協議版本,狀態嗎,狀態英文名稱.
    “HTTP/1.1 200 OK”
  • 響應頭:包含了對服務器的描述,對返回數據的描述.

Content-Encoding: gzip(服務器支持的數據壓縮格式) Content-Length: 1528(返回數據的長度)
Content-Type:application/xhtml+xml;charset=utf-8(返回數據的類型)
Date: Mon,15Jun201509:06:46GMT(響應的時間) Server: apache (服務器類型)

  • 實體內容:服務器返回給客戶端的具體數據(圖片/html/文件…).
  1. 發送http請求
    在iOS開發中,發送http請求的方案有很多,常見的有如下幾種:
  • 蘋果原生:

NSURLConnection:
用法簡單,古老經典的一種方案.
NSURLSession:
iOS7以後推出的技術,功能NSURLConnection更加強大.
CFNetWork:NSURL的底層,純C語言,一般不用.

  • 第三方框架:
    AFNetWorking(OC);Alamofire(swift);

###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:服務端錯誤,服務器不能正確執行一個正確的請求;
詳細描述:狀態碼

#Socket
##Socket 簡介

  • 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 端書寫步驟

  1. 創建客戶端Socket
  2. 創建服務器Socket
  3. 連接到服務器(Socket編程)
  4. 發送數據給服務器
  5. 接收服務器返回的數據
  6. 關閉Socket : close(socketNumber)

一張經典的Socket C/S的步驟圖。
Socket.jpg

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;

操作步驟.gif

S端socket通信步驟

  1. 提供一些服務
  2. 將這個服務與自己的IP地址、端口綁定
  3. 監聽任何到這個IP+端口的TCP請求
  4. 接受/拒絕建立這個TCP連接
  5. 讀寫
  6. 斷開TCP連接

socket服務端下次再談!
以上就是本次回顧。


參考資料1
參考資料2
參考資料3
參考資料4
參考資料5


你的鼓勵也是我創作的動力

打賞地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章