介紹:TCP/IP包含了一系列的協議,也叫TCP/IP協議族,簡稱TCP/IP。該協議族提供了點對點的連接機制,并將傳輸數據幀的封裝、尋址、傳輸、路由以及接收方式都予以標準化
TCP/IP的分層模型
在講TCP/IP協議之前,首先介紹一下七層ISO模型:
七層框架 | 通信協議 |
應用層 | http、smtp、snmp、ftp、telent、sip、ssh、nfs等 |
表示層 | xdr、asn.1、smb、afp、ncp等 |
會話層 | ASAP、ssh、rpc、netbios、asp、winsock、bsd socket等 |
傳輸層 | tcp、udp、tls、rtp、sctp、spx、atp、IL等 |
網絡層 | ip、icmp、igmp、ipx、bgp、ospe、rip等 |
數據鏈路層 | 以太網、HDLC、令牌環、幀中繼、ISDN等 |
物理層 | 銅纜、網纜、光纜、無線電等 |
TCP/IP協議是互聯網最基本的協議,在一定程度上參考了七層ISO模型,有些復雜,所以在TCP/IP協議中的七層被簡化為四個層次。
1、TCP\IP協議的應用層
應用層包含所有和應用程序協同工作并利用基礎網絡交換應用程序的業務數據的協議。一些特定的程序被認為運行在這個層上,該層協議所提供的服務能直接支持用戶應用。應用層協議包含HTTP(萬維網服務)、ftp(文件傳輸)、smtp(電子郵箱)、ssh(安全遠程登錄)、dns(域名解析)等諸多協議。
2、TCP/IP協議的傳輸層
(1)傳輸層的協議解決了端與端連接提供傳輸服務。
(2)這種傳輸服務分為可靠和不可靠的,其中TCP就是可靠傳輸、udp是不可靠傳輸。
(3)為端與端連接提供流量控制、差錯控制、服務質量等管理服務。
傳輸層主要有兩個性質不同的協議:tcp(控制傳輸協議)和UDP(用戶數據協議)。
TCP那邊有一個接受數據的緩存區,通過這個緩存可以解決以下兩個問題:
- 流量控制:接收端可以通過控制緩存區的大小來控制發送端的發送速率,從而避免發送端發送過快導致接收端無法處理的情況。
- 確認機制:接收端可以將已經接收到的數據存放在緩存區中,等待后續的數據到達,當接收到后續的數據時,可以通過確認機制通知發送端已經接收到了哪些數據,從而保證數據的可靠傳輸。
而UDP是一個無連接的數據報協議,它沒有緩存區,實現不了TCP上面的功能,UDP的主要目的是盡力傳遞,其不需要搞這些復雜的操作,所以其傳輸效率是最高的。
3、TCP/IP協議的網絡層
TCP/IP協議網絡層的作用是在復雜的網絡環境中為要發送的數據報找到一個合適的路徑進行傳輸。簡單來說,網絡層負責將數據傳輸到目的地址,目的地址可以是多個網絡通過路由器連接而成的某一地址。路由轉發應該也是由該層完成。網絡協議的代表包括ICMP、IP、IGMP等。
4、TCP/IP協議的鏈路層
鏈路層有時也被稱為數據鏈路層或網絡接口層,用來處理連接網絡的硬件部分。該層既包括操作系統硬件的設備驅動、NIC(網卡)、光纖等物理可見部分,也包括連接器等一切傳輸媒介。在這一層中,數據的傳輸單位為bit(比特)。其主要協議有ARP、RARP等。
HTTP報文傳輸原理
利用TCP/IP進行網絡通信時,數據包會按照分層順序與對方進行通信。發送端從應用層往下走,接收端從鏈路層往上走。從客戶端到服務端的數據,每一幀的傳輸順序都為應用層->傳輸層->網絡層->鏈路層->鏈路層->網絡層->傳輸層->應用層。
接下來為大家介紹一下數據封裝和分用。
數據通過互聯網傳輸時不可能是光禿禿的不加標識(數據會亂),所以在發送數據時需要加上特定的標識(數據封裝),在使用數據時候在去掉特定標識(數據分用)。
1、TCP報文格式
源端口號:
(1)源端口號表示報文的發送端口,占16位。源端口號和源ip地址組合起來,可以標識報文的發送地址。
(2)目的端口號表示報文的接收端口,占16位。目的端口號和目的IP地址相結合,可以標識報文的接收地址
(3)序號,TCP傳輸過程中,在發送端出的字節流中,傳輸報文中的數據部分的每一個字節都有它的編號。序號占32位,發起方發送數據時,都需要標記序號。
序號的語義與syn控制標志(Control bits)的值有關。根據控制標志中的SYN來表示不同的序號含義:
當syn=1時,為連接建立階段
當syn=0時,為數據傳輸正式開始時,第一個報文的序號為isn+1,后面的報文序號為前一個報文的SN值+TCP報文的凈荷字節數(不包含TCP頭)。如果發送端發送的一個TCP幀的凈荷為12B,序號為5 ,則發送端接著發送下一個數據包時,序號的值應該為5+12=17。
在數據傳輸中,tcp通過序號來對上層提供有序的數據流。
(4)確認序號標識了報文接收端期望接收的字節序列。如果設置了ACK控制位,確認序號的值表示下一個準備接收的包的序號碼。舉個例子
(5)頭部長度,該字段占4位,用來表示tcp報文的首部長度。
(6)保留字段,暫時沒什么用。
(7)控制標志占6位,具體的標志位為URG、ACK、psh、rst、syn、fin
(8)窗口,長度為16位,共兩個字節,用來進行流量控制的。
(9)校驗和長度位16位,共兩個字節,對整個tcp報文段,即tcp頭部和tcp數據進行校驗和計算,接收端用于對收到的數據包進行驗證。
(10)緊急指針,長度16位,共兩個字節,是一個偏移量,和sn序號值相加表示緊急數據最后一個字節的序號。
以上10項內容是TCP報文首部必需字段,也叫固有字段,長度為20字節。接下來就是可選項和填充部分。
2、TCP的三次握手
TCP連接建立時,雙方需要經過三次握手;斷開連接時,雙方需要經過四次揮手。
通常情況下,建立連接的雙方由一端監聽來自請求方的TCP連接,當服務端監聽開始時,必須準備好接受外來的連接,在java中該操作通過創建一個ServerSocket服務監聽套接字實例來完成。此操作會調用操作系統(如linux)c代碼的三個函數socket()、bind()、listen()來完成
服務端偽代碼如下:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;public class SocketServer {public static void main(String[] args) {try {ServerSocket socket=new ServerSocket(8080);while (true){Socket socket1=socket.accept();//開啟線程進行連接的IO操作ServerThread thread=new ServerThread();thread.start();}} catch (IOException e) {throw new RuntimeException(e);}}
}
客戶端偽代碼如下:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;public class SocketClient {public static void main(String[] args) {try {Socket socket =new Socket("localhost",8080);//寫入給監聽方的輸出流。OutputStream os=socket.getOutputStream();//讀取監聽方的輸入流InputStream inputStream=socket.getInputStream();} catch (UnknownHostException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}
}
(1)第一次握手:Client進入SYN_SENT狀態,發送一個SYN幀來主動打開傳輸通道,該幀被設置為1
(2)第二次握手:Server在收到SYN幀之后,會進入SYN_RCVD狀態,同時返回SYN+ACK幀給client。
(3)第三次握手:Client在收到Server的第二次握手SYN+ACK確認幀之后,首先將自己的狀態從SYN_SEND變成ESTABLISHED,表示自己的放向的連接通道已經建立成功。