TCP 学习笔记 --阿太

 

               TCP 学习笔记  --- Kindda Hu

                                         08.12.15  [email protected]

 

Reference: TCP/IP详解卷一/ RFC793 /

 

以下是个人总结, 语言方面若有看不习惯请见谅. 还有几点不明白之处请指教,请参考#Issues to be comfired. 若本人总结有错误之处,请各位及时指出并告知.

 

 

########## TCP Header ###################

 

 TCP Header Format 20Bytes

 

 

##########  TCP 基本传输流程#################

 

                                            Sender A ---------------->  Receiver  B

Step 1:Start 3-hands shake                

                                                     SYN seq j ,mss ,win

                                             a,    ------------------------->

                                                   SYN seq q,mss,win; ACK ack j+1

 

                                             b,   <-------------------------

                                                     seq j+1 ACK ack q+1

                                             c,    ------------------------->

 

Step 2: Data flow  

       2.1 数据不需要分组,                     

                                                   seq j+1, ack NO (Length), 

                                             d,   ------------------------->

                                                   ack (j+length+1), win size

                                             e,   <-------------------------

                                                

     2.1 数据包进行分组转发,绝大多数都需要如此发送:

                                                   

                                                   seq j+1, ack seq no (Length), 

                                              f,   ------------------------->

                                                   ack (j+length+2), win size

                                              g,  <------------------------- 

 

                                                 seq j+length,ack no(length),win size,

                                              h,   ------------------------->

 

                                                seq (j+length+length),ack no(length),win size,

                                              i,   ------------------------->

                                                  ack j+length+1;win size

                                              j,  <-------------------------

                                                  ack j+length+length+1;

                                              k,   ------------------------->

                                                      .................

 

                                                

Step 3, Close. FIN  4 hands shake

                                                 Fin seq j',

                                              l  ------------------------->     

                                                ACK seq j'+1

                                             m <-------------------------  

                                                Fin seq q'

                                              n <------------------------- 

                                                ACK seq q'+1

                                              o ------------------------->  

 

 

Step1 ,  TCP 建立, 3次握手; 下面为正常的TCP session建立过程;

           a. A主动建立TCP连接, 发送SYN , seq no为当前定时器给的值j(参见关于SEQ NO),宣称自己的MSS, window size;

           b. B回复ACK, ack no = j+1,并同时发SYN包给发A, seq noB自身定时器的值q, 并宣称自己的msswin size;

           c. A收到B发来的SYN包后回复ACK, ack no=q+1;

  ps: Step1为标准的正常TCP session建立流程,还有一些非正常现象,AB同时向对方发送SYN,则通过4次握手只建立一个TCP            session;

 

Step2,   数据传输, TCP session建立后,AB发送数据包

      2.1  数据不需要分组传输,每个数据包单独传输.

           d. AB发送数据包,Seq noj+1,和步骤c中的seq no相同, 因为A并没有收到B发送新的ack no,length为数据的长度(因为需要发               送的数

 

据字节长度小于MSSwin size,所以不需要分段), (参考关于数据包分组(分段)传输标准);

           e. B收到数据后给A回复ACK, ack noj+1+length;

 ps:

      2.2  数据需要进行分组传输

           f. AB发送一个数据报文,seq noj+1, 长度为length;

           g.BA刚才的data报文回复ACK, ack noj+1+length+1;

           h.A收到B对于刚发送data包的ack, 使用其ack no作为seq no发送数据,lengthl';

           i. A使用seq no j+1+length+1+L'再次发送数据报文; (连续发送两个数据包. 发送方接收到一个ack则增加一个发送数据包.因为使用了慢启动. 详情

 

请参照 关于慢启动)

           j. B收到2data包后回复ack(根据网络情况和b决定. 只回复一个ack或者针对每个data都回复ack. 具体参考关于接收方什么时候回复ACK报文)

           k. 很步骤h类似, 这次发送的data数根据收到的ack报文来决定,收到n个则再增加n;

 

Step3, 结束TCP Session,

        TCP session的结束类似于TCP session的建立(只不过将给对方的ack和自己的fin请求区分开了), 需要分别想对方发送FIN请求,并得到对方的ack

 

close掉此链接;

           l. 当数据发送完成后,发送方A给接收方B发送FIN结束请求, seqj';

          m.B收到Fin,回复ACK报文给A;

           n.BA发送FIN请求结束报文;

           o.A收到ACK后结束对BTCP 状态调整为closed; 并在收到B发送的Fin,回复ACKB; B在收到ack后将自己对于Atcp状态调整为closed;

 ps: 有的TCP版本中,结束时只进行单方面结束,即两次握手,ABFIN,B回复ACK,但是不发送Fin请求;

            

 

 

######### TCP 状态变迁 ###############

 

# 如下图为TCP状态机图

 

 

#如下图为正常的T C P连接的建立与终止过程中,客户与服务器所经历的不同状态。

Ps: 主动结束的需要先进入Time-wait状态后经过2MSL后进入Closed状态;

 

 

 

   被动结束的,只需要在LAST-ACK状态中收到ACK回复即可进入Clolse状态;

因为提出主动结束的大都为客户端,所以服务器被动结束,直接进入Closed状态.

 

 

### 下面为TCP 各种状态的具体说明

A connection progresses through a series of states during its

lifetime. The states are: LISTEN, SYN-SENT, SYN-RECEIVED,

ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK,

TIME-WAIT, and the fictional state CLOSED.

CLOSED is fictional because it represents the state when there is no TCB, and therefore,no connection. Briefly the meanings of the states are:

 

LISTEN - represents waiting for a connection request from any remote

TCP and port. 监听状态;

 

SYN-SENT - represents waiting for a matching connection request

after having sent a connection request. Syn已经发出状态;

 

SYN-RECEIVED - represents waiting for a confirming connection

request acknowledgment after having both received and sent a

connection request. 收到SYN,回复ack并发送SYN;

 

ESTABLISHED - represents an open connection, data received can be

delivered to the user. The normal state for the data transfer phase

of the connection. 收到针对自己发出SYN包的ACK报文,则变成Estab状态;

 

FIN-WAIT-1 - represents waiting for a connection termination request

from the remote TCP, or an acknowledgment of the connection

termination request previously sent. 主动结束中,发送FIN报文,并等待ACK或者Fin的阶段;

 

FIN-WAIT-2 - represents waiting for a connection termination request

from the remote TCP. 主动结束中,接收到针对自己发出FIN包的ACK.并等待对方FIN包的阶段;

 

CLOSING - represents waiting for a connection termination request

acknowledgment from the remote TCP. 主动结束中,FIN-Wait1状态,等待对方ACK包的过程中收到对方的主动结束请求FIN,则进入CLOSING阶段;

 

TIME-WAIT - represents waiting for enough time to pass to be sure

the remote TCP received the acknowledgment of its connection

termination request.

 

CLOSE-WAIT - represents waiting for a connection termination request

from the local user.被动结束中,收到对方的FIN请求,回复ACK报文的阶段;

 

LAST-ACK - represents waiting for an acknowledgment of the

connection termination request previously sent to the remote TCP

(which includes an acknowledgment of its connection termination

request). 被动结束中,COLSE-WAIT的基础上,发送FIN请求后,等待ACK报文的阶段 ;

 

CLOSED - represents no connection state at all. 主动结束时,Time-WAIT经过2msl到达Colsed; 被动结束时, LAST-ACK报文收到最后的ack后进入的状态.

 

 

################## 相关概念 ###########################3

 

sender 相关概念:MTU,MSS,window size 的左边, Cwnd(congetion window size) 慢启动门限ssthresh, RTT, RTO,

Receiver 相关概念: MRU,MSS,window size的右边,  window size,buffer size, tcp 处理进程, 回复ack. window size buffer size seq no ack no

 

 

#关于PUSH标记

若接收方收到一个带PSH标志的包,则立即提交到TCP进程进行处理,并回复ACK.  若数据包中不带PSH标记, 则是由分组到齐或者buffer size到一定程度上将数据

 

提交到TCP处理进程中.

 

#关于SEQ NO

seq NO 为数据包发送的序列号, TCP 报头中包括Seq no ack seq NO,分别占4个字节,  所以其值为[ 0- 65535x65535].

第一个syn包中的seq no值由发送方的定时器决定. Seq No 由一个定时器维护着,每隔4ms, seq+1, 达到最大值后继续冲最小值开始循环, 如此反复;

数据传输时的seq no (我认为)ack回复的ack no为准, = sender's seq +1;也可是发送方的原seq no+Length+1; (RFC793中如此规定,但是也有不同实现的.)

 

#关于DATA Offset

数据开始的偏移位数,就是说从x个字节开始为数据, x之间的为TCP Header,所以也可解释为TCP 头部的长度.   但是x=nx4;offset4bit1000的话,10进制为8,所以tcp header长度为8x4=32;

 

###### 关于定时器 ##########

## 关于坚持定时器 Persist Timer:

 即窗口大小检测定时器, 发送方通过该定时器定期查询接收方窗口状态. 防止一下情况产生,

a,  receever win size0,并通知sender,sender 暂停发送报文,并等待窗口更新报文ack的到来;

b,  receiver 窗口更新, 发送ack通知sender,但是该ack包被丢失.

c,  则出现了, sender 等待win size更新报文,不发送数据; receiver 等待sender发送新的数据的 双方互等的情况发生.

 

persist timer 在收到win size0ack包时被启动,然后每隔一段(5s)时间进行查询.

receiver window size 需要从从0更新到大于1/2buffer size的时候,才告知sender,否则仍然宣称win = 0 ;

 

## 关于保活定时器 Keepalive Timer:

可以理解为TCP Session timeout keepalive time, 当建立好的tcp session处于空闲时,双方都处于Established状态,保活定时器则可以在一段时间以后自动停

 

止该tcp session.   但是RFC和有的TCP版本并不支持该定时器.

 

## 关于2MSL 定时器 

 

 

 

 

##关于判断是否分组的标准:

首先理解下面几个概念: 需要传输的数据字节数, MSS,MTU, Window size;

#关于需要传输的数据字节数.

既被传输数据的字节个数. ("Hello World"10个字节.若每次只发送一个hello world,则每次为10个字节; 若一次发送200hello word,则需要传输的字节数

 

2000个字节;)

#关于MSS/MTU/WINDOW SIZE则参考关于MSS,关于MTU和关于Window size;

 

#关于MTU

MTU 为最大传输单元,基于不同的链路层的. Ehternet MTU 1518, SLIP259,  所以相对为IP层来说,MTU= 1518-18(DMAC 6+SMAC 6+

 

TYPE/LENGTH 2+ CRC 4)= 1500; 相对于PPPoE来说,MTU= 1492=1500-8(PPP);

 

#关于MSS

MSS TCP协议里面的一个概念,为发送端最大发送的TCP报文中数据字段的大小,必须小于MTU,通常为 1460=

 

MTU-IPHead-TCPhead=1500-20-20=1460;

A-B都在同一网段,MSS1460,若不在同一网段,而且程序没有指定的话,使用默认536;

MSS一般在TCP session建立阶段 三次握手时宣称和协商.

 

#window size

window size  接收端用来申明自己可以接收到的数据大小为窗口;  接收端用此来处理数据拥塞;

数据传输时, 窗口是滑动的, 可以理解为窗口大小为从AB,A代表窗口的左边, B代表窗口的右边, 所以Window size == B-A; 在传输过程中BA都向后滑动,

 

B=A, window size == 0, 接收方此时不能接收任何数据, 并通知发送方让其停止发送数据, 当窗口大小更新后,发送ack通知sender告知window 大小,

 

sender继续发送数据.

发送端左边A向右移动,是因为受到接收端的ack包,并将左边A移动到ack no的地方.

接收端window size右边B向右移地取决于, 接收端进程处理tcp数据并释放缓存的能力。 当缓存没有释放完全时,接收端则通过ack给发送端通告当前window

 

size的大小,待恢复或者变大时,发ack包通知, ack no和之前的ack包中的no 相同。 所以说buffer可以大于缓存。

接收方回复ACK的时机 取决于接收方window size的大小(接收方在发送一个A C K前不必等待窗口被填满)和接收到的包中是否带有PUSH标记.)?

 

下面说一下我对于什么时候需要对数据包分段的理解:

比如说一个正常的数据传输, MSS=1460,MTU=1500,Win size=65535; 当前win sizeB通告的为win size',

1, 当要发送数据字节个数<MSS;且又<win size' ; 不需要分组发送; 如发送hello word 或者通过telnet登录时传输user/password的报文;

2, 当要发送数据字节数>MSS;且又>win size', 则需要进行分组发送;ftp传输大文件,或者一次传输200hello world(注意:一次发送200hello world和发

 

200hello word是不一样的. 前者需要分组,2date报文搞定(length分别是1460+540)和一个ack报文;而后者则需要200date报文(每个length=10),

 

x(有时为200,有时为x,请参考关于接收方什么时候回复ACK报文)ack报文.);

 

 

##关于如何决定是否重发数据包.(如何界定包已经丢失并重传?)    

1,RTO超时;

2,连续收到3个相同Seq noack,发送方则认为丢包.

                                                                

 

#### TCP 对分组包丢失的处理 #########

当分组传输的数据被丢失后, 接收端通过对收到的数据进行处理发现后,必须发送ack报文通知发送方重新发送. 

因为TCP无法告知对方缺少那一段,所以采用发送方将自己最后一个成功回复的ack包发送给对方的方式,来告诉对方应该从该seq no处将数据包进行重发.

发送方连续收到3个相同的ACK, 则认为有包被丢弃,并重传自那个序号起的一段报文.

当接收方处于通知对方丢包并且在等待丢失包到来的状态时, 对收到的数据包只进行保存,不会上传到进程进行处理.

当接收方收到丢失包且发现没有其他丢包时, 将缓存的数据全部提交给进程进行处理.

 

# 慢启动和拥塞避免

Congetion window 发送端每次发送数据包的个数大小,cwnd<= ssthresh,每当收到一个ack,cwnd+1; cwnd>ssthersh,则每次增

 

1/cwnd,cwnd=cwnd+1/cwnd. 发送方用此来进行数据拥塞的处理.

 

 

 

## 关于重传超时定时器 Retransmission TimeOut / RTT :

RTO 为超时重传时间. RTO时间内未收到对方的ack,则认为超时,重发数据包;

RTO值是有RTT计算出来, RTT 为往返时间, 为发送方发出一个seq no的报文,到收到该报文ack 回复的时间段.由于网络流量变化,所以TCP需要跟踪这些变化,

 

并算出相应的值;  所以TCP中判断是否超时,重传最主要的就是要进行RTT的计算.

sender 每次发送数据要先检测RTT 测量定时器是否被启动,若没有的话则启动该定时器, 若已经启动的话则不更新.

因为TCPackseq no的回复并不可能是一一对应,所以需要算法来计算RTT的值;

 

 

 

### Issues to be confirmed  #####

1, 接收方什么时候会将buffer中的数据提交到TCP进程当中去?

  包中带psh标记, buffer 到什么程度? 还是等分组全部收到? 或者自己有什么定时器?

 

2, TCP 不对ack报文进行确认,只对带有带有数据的ack报文进行确认.  应该如何理解!!????????

 

3, RTO 本身有定时器? rtt测量定时器!? 是否是每次发送方发送数据前要确认启动的定时器?

 

4,关于接收方B什么时候回复ACK报文?

 

5,关于2MSL 定时器 

 

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