編寫:Leaf Zhou
EMAIL:leaf_zhou_8@hotmail.com
TCP是英文Transport Control Protocol的縮寫。從字面理解,就是傳輸控制協(xié)議。因此,TCP是一種控制協(xié)議,他本身不能用來(lái)傳輸數(shù)據(jù),它需要通過(guò)網(wǎng)絡(luò)層的IP協(xié)議來(lái)進(jìn)行實(shí)際數(shù)據(jù)的傳輸。這也就是我們常常看到,TCP/IP和TCP/UDP總是同時(shí)出現(xiàn)的原因。因此,也可以理解為TCP是很多的不同的協(xié)議組成,實(shí)際上是一個(gè)協(xié)議組。提供可靠的主機(jī)到主機(jī)層數(shù)據(jù)傳輸控制協(xié)議。這里要先強(qiáng)調(diào)一下,傳輸控制協(xié)議是OSI網(wǎng)絡(luò)的第四層的叫法,TCP傳輸控制協(xié)議是TCP/IP傳輸?shù)?個(gè)基本協(xié)議的一種。TCP是一種可靠的面向連接的傳送服務(wù)。它在
一、TCP概述
TCP是英文Transport Control Protocol的縮寫。從字面理解,就是傳輸控制協(xié)議。因此,TCP是一種控制協(xié)議,他本身不能用來(lái)傳輸數(shù)據(jù),它需要通過(guò)網(wǎng)絡(luò)層的IP協(xié)議來(lái)進(jìn)行實(shí)際數(shù)據(jù)的傳輸。這也就是我們常常看到,TCP/IP和TCP/UDP總是同時(shí)出現(xiàn)的原因。因此,也可以理解為TCP是很多的不同的協(xié)議組成,實(shí)際上是一個(gè)協(xié)議組。提供可靠的主機(jī)到主機(jī)層數(shù)據(jù)傳輸控制協(xié)議。這里要先強(qiáng)調(diào)一下,傳輸控制協(xié)議是OSI網(wǎng)絡(luò)的第四層的叫法,TCP傳輸控制協(xié)議是TCP/IP傳輸?shù)?個(gè)基本協(xié)議的一種。TCP是一種可靠的面向連接的傳送服務(wù)。它在傳送數(shù)據(jù)時(shí)是分段進(jìn)行的,主機(jī)交換數(shù)據(jù)必須先建立一個(gè)會(huì)話。它用比特流通信,即數(shù)據(jù)被作為無(wú)結(jié)構(gòu)的字節(jié)流進(jìn)行傳輸,沒(méi)有數(shù)據(jù)邊界。通過(guò)每個(gè)TCP傳輸?shù)淖侄沃付樞蛱?hào),以獲得可靠性。是在OSI參考模型中的第四層,TCP是使用IP的網(wǎng)間互聯(lián)功能而提供可靠的數(shù)據(jù)傳輸,IP不停的把報(bào)文放到網(wǎng)絡(luò)上,而TCP是負(fù)責(zé)確信報(bào)文到達(dá)。在協(xié)同IP的操作中TCP負(fù)責(zé):握手過(guò)程、報(bào)文管理、流量控制、錯(cuò)誤檢測(cè)和處理(控制),可以根據(jù)一定的編號(hào)順序?qū)Ψ钦m樞虻膱?bào)文給予從新排列順序。關(guān)于TCP的RFC文檔有RFC793、RFC791、RFC1700。
二、TCP連接的建立
建立一個(gè)TCP連接,需要下面的步驟:
(1)服務(wù)器端通過(guò)listen來(lái)準(zhǔn)備接受外來(lái)的連接,稱為被動(dòng)打開(passive open)。
(2) 客戶端通過(guò)connect進(jìn)行連接服務(wù)器,稱為主動(dòng)打開(active open)。在這個(gè)操作中,客戶端需要發(fā)送一個(gè)同步數(shù)據(jù)報(bào)(SYN),用來(lái)通知服務(wù)器端開始發(fā)送數(shù)據(jù)的初始序列號(hào)。通常情況下,同步數(shù)據(jù)報(bào)不攜帶數(shù)據(jù),它只包含一個(gè)IP頭部、一個(gè)TCP頭部和本次通信所使用的TCP的選項(xiàng)。
(3)服務(wù)器端必須對(duì)客戶端發(fā)來(lái)的同步數(shù)據(jù)報(bào)SYN進(jìn)行確認(rèn),同時(shí)自己也要發(fā)送一個(gè)同步數(shù)據(jù)報(bào)(SYN),它包含客戶端發(fā)送數(shù)據(jù)的初始序列號(hào)。服務(wù)器端對(duì)在同一連接中發(fā)送的數(shù)據(jù)初始序號(hào)和對(duì)客戶端發(fā)送的確認(rèn)信息(ACK),都放在一個(gè)數(shù)據(jù)報(bào)中,一起發(fā)送給客戶端。
(4)客戶端也必須發(fā)送確認(rèn)服務(wù)器端的同步數(shù)據(jù)報(bào)(SYN)。
由上面的步驟來(lái)看,建立一個(gè)TCP連接,至少需要服務(wù)器端和客戶端進(jìn)行三個(gè)分組數(shù)據(jù)的交換,因此,稱之為TCP的三路握手(three-way handshake)。
????????????客戶端???????????????????????????服務(wù)器端
????????????connect()????????????????????????accept()
????????????????????? --->?SYN?S?----->???
??????????????????????<---?SYN?C
,
ACK?S+
1
?<---??????
??????????????????????--->?ACK?C+
1
?----->
第一次進(jìn)行分組數(shù)據(jù)交換的過(guò)程中,分組數(shù)據(jù)中可能包含著本次通信中可能的TCP選項(xiàng)。這些選項(xiàng)有:
(1) 最大分組(MSS)選項(xiàng)。TCP發(fā)送的SYN中帶有這個(gè)選項(xiàng),用來(lái)告訴對(duì)方它的最大分組數(shù)據(jù)的大小MSS(Maximum Segment Size),即它能接收的每個(gè)TCP分組數(shù)據(jù)中的最大數(shù)據(jù)量。這個(gè)選項(xiàng)可以通過(guò)TCP_MAXSEG套接口選項(xiàng)獲取與設(shè)置這個(gè)TCP選項(xiàng)。
(2) 窗口大小選項(xiàng)。這是TCP能提供流量控制的主要手段。TCP連接的每一方都有固定大小的緩沖空間,TCP的接收端只允許另一端發(fā)送接收端緩沖區(qū)所能接納的數(shù)據(jù)。這將防止較快主機(jī)致使較慢主機(jī)的緩沖區(qū)溢出。TCP雙方能夠通知對(duì)方的最大窗口大小是64K(65535 bytes),因?yàn)門CP頭部相應(yīng)的標(biāo)識(shí)字段值只用了16位來(lái)表示。每個(gè)套接口都有一個(gè)發(fā)送緩沖區(qū)和一個(gè)接收緩沖區(qū),接收緩沖區(qū)被TCP和UDP用來(lái)將接收到的數(shù)據(jù)一直保存到由應(yīng)用進(jìn)程來(lái)讀取。對(duì)于TCP,TCP通告另一端的窗口大小。 TCP套接口接收緩沖區(qū)不可能溢出,因?yàn)閷?duì)方不允許發(fā)出超過(guò)所通告窗口大小的數(shù)據(jù)。這就是TCP的流量控制,如果對(duì)方無(wú)視窗口大小而發(fā)出了超過(guò)窗口大小的數(shù)據(jù),則接收方TCP將丟棄它;而對(duì)于UDP,當(dāng)套接口接收緩沖區(qū)放不下接收到的數(shù)據(jù)報(bào)時(shí),此數(shù)據(jù)報(bào)就被丟棄。UDP是沒(méi)有流量控制的,快的發(fā)送者可以很容易地就淹沒(méi)慢的接收者,導(dǎo)致接收方的UDP丟棄數(shù)據(jù)報(bào),使數(shù)據(jù)發(fā)生丟失。
(3)時(shí)間戳選項(xiàng)。時(shí)間戳選項(xiàng)使發(fā)送方在每個(gè)報(bào)文段中放置一個(gè)時(shí)間戳值。接收方在確認(rèn)中返回這個(gè)數(shù)值,從而允許發(fā)送方為每一個(gè)收到的ACK計(jì)算RTT。
三、TCP連接的終止
終止TCP連接
TCP用三個(gè)分組數(shù)據(jù)建立一個(gè)連接,但要終止一個(gè)連接則通常需要需要四個(gè)分組數(shù)據(jù)。過(guò)程如下:
(1)先調(diào)用close的進(jìn)程,稱為主動(dòng)關(guān)閉(active close)。這一端的TCP先發(fā)送一個(gè)FIN分組數(shù)據(jù),告訴對(duì)方,數(shù)據(jù)發(fā)送完畢。
(2)接收到FIN分組數(shù)據(jù)的一端執(zhí)行被動(dòng)關(guān)閉(passive close),同時(shí),發(fā)送對(duì)這個(gè)FIN的確認(rèn)ACK分組數(shù)據(jù)給對(duì)方。確認(rèn)序號(hào)為收到的序號(hào)加1。FIN分組數(shù)據(jù)的接收意味著在當(dāng)前的連接上,再也不會(huì)收到額外的數(shù)據(jù)。
(3)接收到FIN分組數(shù)據(jù)的一端的應(yīng)用進(jìn)程,將調(diào)用close關(guān)閉自己的套接口,同時(shí)TCP 會(huì)發(fā)送一個(gè)FIN分組數(shù)據(jù)給另一端。
(4)收到這個(gè)FIN的分組數(shù)據(jù),即執(zhí)行主動(dòng)關(guān)閉的一端對(duì)這個(gè)FIN分組數(shù)據(jù)進(jìn)行確認(rèn)。發(fā)回確認(rèn)ACK分組數(shù)據(jù),并將確認(rèn)序號(hào)設(shè)置為收到序號(hào)加1
在這個(gè)過(guò)程中,執(zhí)行被動(dòng)關(guān)閉的一方可以把確認(rèn)對(duì)方FIN分組數(shù)據(jù)的ACK分組數(shù)據(jù)和自己要發(fā)送的FIN分組數(shù)據(jù)可以放到一個(gè)分組數(shù)據(jù)中。TCP的連接終止的過(guò)程如下:
????????????客戶端???????????????????????????服務(wù)器端
????????????close()??????????????????????????close()
??????????????????????--->?FIN?S?----->???
??????????????????????<---?ACK?S+
1
?<---??????
??????????????????????<---?FIN?C???<---
??????????????????????--->?FIN?C+
1
?--->
四、TCP連的狀態(tài)?????????????????
TCP的連接的建立和終止,基本上已經(jīng)清楚了,那么在這個(gè)過(guò)程中,是如何知道這個(gè)連接正處在什么狀態(tài)呢?方法當(dāng)然是有的,我們先運(yùn)行如下命令,看看返回的結(jié)果:
[root@linux81?leaf]#?netstat?-an
Active?Internet?connections?(servers?and?established)
Proto?Recv-Q?Send-Q?Local?Address???????????Foreign?Address?????????State????
tcp????????0??????0?0.0.0.0:3306????????????0.0.0.0:*???????????????LISTEN????
tcp????????0??????0?0.0.0.0:139?????????????0.0.0.0:*???????????????LISTEN????
tcp????????0??????0?0.0.0.0:21??????????????0.0.0.0:*???????????????LISTEN????
tcp????????0??????0?0.0.0.0:22??????????????0.0.0.0:*???????????????LISTEN????
tcp????????0??????0?0.0.0.0:23??????????????0.0.0.0:*???????????????LISTEN????
tcp????????0??????0?192.168.253.81:139??????192.168.253.35:1201?????ESTABLISHED
tcp????????0????272?192.168.253.81:22???????192.168.253.59:1776?????ESTABLISHED
udp????????0??????0?192.168.253.81:137??????0.0.0.0:*?????????????????????????
udp????????0??????0?0.0.0.0:137?????????????0.0.0.0:*?????????????????????????
udp????????0??????0?192.168.253.81:138??????0.0.0.0:*?????????????????????????
udp????????0??????0?0.0.0.0:138?????????????0.0.0.0:*?????????????????????????
udp????????0??????0?127.0.0.1:36260?????????0.0.0.0:*??????????
在上面的返回結(jié)果中,State一列,就是說(shuō)明連接的當(dāng)前狀態(tài)。
TCP的連接狀態(tài)有:
(01)CLOSED??
(02)LISTEN??? 被動(dòng)打開
(03)SYN_RCVD??
(04)SYN_SEND
(05)ESTABLISHED?? 數(shù)據(jù)傳送狀態(tài)
(06)CLOSE_WAIT
(07)LAST_ACK?? 被動(dòng)關(guān)閉
(08)FIN_WAIT_1
(09)FIN_WAIT_2
(10)CLOSING
(11)TIME_WAIT
TCP連接狀態(tài)轉(zhuǎn)換示意圖如下所示:
??????????????????????????????+---------+?---------\??????active?OPEN
??????????????????????????????|??CLOSED?|????????????\????-----------
??????????????????????????????+---------+<---------\???\???create?TCB
????????????????????????????????|?????^??????????????\???\??snd?SYN??
???????????????????passive?OPEN?|?????|???CLOSE????????\???\?????????
???????????????????------------?|?????|?----------???????\???\???????
????????????????????create?TCB??|?????|?delete?TCB?????????\???\?????
????????????????????????????????V?????|??????????????????????\???\???
??????????????????????????????+---------+????????????CLOSE????|????\?
??????????????????????????????|??LISTEN?|??????????----------?|?????|
??????????????????????????????+---------+??????????delete?TCB?|?????|
???????????????????rcv?SYN??????|?????|?????SEND??????????????|?????|
??????????????????-----------???|?????|????-------????????????|?????V
+---------+??????snd?SYN,ACK??/???????\???snd?SYN??????????+---------+
|?????????|<-----------------???????????------------------>|?????????|
|???SYN???|????????????????????rcv?SYN?????????????????????|???SYN???|
|???RCVD??|<-----------------------------------------------|???SENT??|
|?????????|????????????????????snd?ACK?????????????????????|?????????|
|?????????|------------------???????????-------------------|?????????|
+---------+???rcv?ACK?of?SYN??\???????/??rcv?SYN,ACK???????+---------+
???|???????????--------------???|?????|???-----------????????????????
???|??????????????????x?????????|?????|?????snd?ACK??????????????????
???|????????????????????????????V?????V??????????????????????????????
???|??CLOSE???????????????????+---------+????????????????????????????
???|?-------??????????????????|??ESTAB??|????????????????????????????
???|?snd?FIN??????????????????+---------+????????????????????????????
???|???????????????????CLOSE????|?????|????rcv?FIN???????????????????
???V??????????????????-------???|?????|????-------???????????????????
+---------+??????????snd?FIN??/???????\???snd?ACK??????????+---------+
|??FIN????|<-----------------???????????------------------>|??CLOSE??|
|?WAIT-1??|------------------??????????????????????????????|???WAIT??|
+---------+??????????rcv?FIN??\????????????????????????????+---------+
???|?rcv?ACK?of?FIN???-------???|????????????????????????????CLOSE??|
???|?--------------???snd?ACK???|???????????????????????????-------?|
???V????????x???????????????????V???????????????????????????snd?FIN?V
+---------+??????????????????+---------+???????????????????+---------+
|FINWAIT-2|??????????????????|?CLOSING?|???????????????????|?LAST-ACK|
+---------+??????????????????+---------+???????????????????+---------+
???|????????????????rcv?ACK?of?FIN?|?????????????????rcv?ACK?of?FIN?|
???|??rcv?FIN???????--------------?|????Timeout=2MSL?--------------?|
???|??-------??????????????x???????V????------------????????x???????V
????\?snd?ACK?????????????????+---------+delete?TCB?????????+---------+
?????------------------------>|TIME?WAIT|------------------>|?CLOSED??|
??????????????????????????????+---------+???????????????????+---------+
????????????????????? TCP Connection State Diagram
從上面的圖表中,可以做出如下總結(jié):
服務(wù)器端的正常狀態(tài)轉(zhuǎn)換過(guò)程如下:
? CLOSED --> LISTEN --> SYN_RCVD --> ESTABLISHED --> CLOSE_WAIT --> LAST_ACK --> CLOSED
客戶端的正常狀態(tài)轉(zhuǎn)換過(guò)程如下:
CLOSED --> SYN_SENT --> ESTABLISHED --> FIN_WAIT_1 --> FIN_WAIT_2 --> TIME_WAIT --> CLOSED
從上面的連接狀態(tài)轉(zhuǎn)換中可以看出,從ESTABLISHED狀態(tài)的轉(zhuǎn)換有兩種,對(duì)于客戶端和服務(wù)器端來(lái)說(shuō),是一樣的,即當(dāng)收到FIN數(shù)據(jù)報(bào)之前,主動(dòng)關(guān)閉,則轉(zhuǎn)換成FIN_WAIT_1;如果因?yàn)槭盏紽IN數(shù)據(jù)報(bào),而引起的被動(dòng)關(guān)閉,則轉(zhuǎn)換成CLOSE_WAIT狀態(tài)。